I/O流·字符流

字符流FileReader

* A:字符流是什么
  * 字符流是可以直接读写字符的 IO流
  * 字符流读取字符,就要先读取到字节数据,然后转换为字符;如果要写出字符,需要把字符转换为字节再写出

* B:FileReader
  * FileReader类的read() 方法可以按照字符大小读取

package com.heima.chario;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException; public class Demo1_FileReader { public static void main(String[] args) throws IOException {
// demo1();
// demo2();
} public static void demo2() throws FileNotFoundException, IOException {
FileReader fr = new FileReader("xxx.txt");
int c; // 默认返回的是int类型 while ((c = fr.read()) != -1) { // 通过项目默认的码表,一次读取一个字符
System.out.println((char) c); // 强转为char类型
}
fr.close();
} public static void demo1() throws FileNotFoundException, IOException {
FileReader fr = new FileReader("xxx.txt"); // 创建字符输入流
char c = (char) fr.read(); // 读取一个字符并强转为char类型 System.out.println(c);
fr.close(); // 关流
}
}

FileReader

字符流FileWriter

* A:FileWriter类的 write()方法可以自动把字符转为字节写出

package com.heima.chario;

import java.io.FileWriter;

public class Demo2_FileWriter {

    public static void main(String[] args) throws Exception {
FileWriter fw = new FileWriter("yyy.txt"); // 创建字符输出流
fw.write("大家好,基础班快接近尾声了,大家要努力啊!!"); // 写入字符串,底层通过编码表翻译后用字节写入
fw.write(97);
fw.close(); // 关流
}
}

FileWriter

什么情况下使用字符流

* 字符流也可以拷贝文本文件,但不推荐是同,因为读取时会把字节转为字符,写入时会把字符转为字节
* 程序如果只需要读取一段文本或者只需要写出一段文本的时候,可以使用字符流
  * 因为读取的时候是按照字符的大小读取的,不会出现半个中文的情况
  * 写入的是红可以直接将字符串写出,不用转换为字节

* 字符流不可以拷贝非纯文本文件
  * 因为再读的时候会将字节转换为字符,在转换的过程中可能找不到对应的字符,就会用?代替
  * 如果读取为?,写出时也是?的字节,这样文件的乱码了

用字符流拷贝文件

* A:普通字符流拷贝

* B:带缓冲的字符流
  * BufferedReader的 read()方法读取字符时会一次读取若干个字符到缓冲区,然后逐个返回给程序,降低读取文件的次数,提高效率
  * BufferedWriter的 write()方法写出字符时会先写到缓冲区,缓冲区写满后才会写到文件,降低写文件的次数,提高效率

package com.heima.chario;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException; public class Demo3_Copy { public static void main(String[] args) throws IOException {
// demo1();
// demo2();
// demo3();
// demo4();
} public static void demo4() throws FileNotFoundException, IOException {
BufferedReader br = new BufferedReader(new FileReader("xxx.txt")); // 创建带缓冲的字符输入流,关联普通字符输入流
BufferedWriter bw = new BufferedWriter(new FileWriter("yyy.txt")); int c;
while ((c = br.read())!= -1) {
bw.write(c);
} br.close();
bw.close();
} public static void demo3() throws FileNotFoundException, IOException {
FileReader fr = new FileReader("xxx.txt"); // 创建字符输入流
FileWriter fw = new FileWriter("yyy.txt"); // 创建字符输出流 char[] arr = new char[1024 * 8]; // 创建字符数组接收数据
int len;
while ((len = fr.read(arr)) != -1) { // 将文件上的数据读取到字符数组中
fw.write(arr, 0, len); // 将字符数组中的数据写到文件上
}
fr.close();
fw.close();
} public static void demo2() throws FileNotFoundException, IOException {
// 字符流不能拷贝非纯文本文件
FileReader fr = new FileReader("亲爱的小孩.mp3");
FileWriter fw = new FileWriter("copy1.mp3"); int c;
while ((c = fr.read()) != -1) {
fw.write(c);
}
fr.close();
fw.close();
} public static void demo1() throws FileNotFoundException, IOException {
FileReader fr = new FileReader("xxx.txt"); // 创建字符输入流
FileWriter fw = new FileWriter("zzz.txt"); // 创建字符输出流 int c; // 接收每一个字符
while ((c = fr.read()) != -1) {
fw.write(c); // 将读取到的内容写入文件
} fr.close(); // 关流
fw.close(); // Writer类中有一个2k的小缓冲区,程序会将内容写到缓冲区内,关流会将缓冲区内的内容刷新到硬盘上
}
}

Copy

readLine() 和 newLine() 方法

* BufferedReader的 readLine()方法可以读取一行字符(不包含换行符)

* BufferedWriter的 newLine()方法可以输出一个跨平台的换行符

package com.heima.chario;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException; public class Demo4_Buffered {
/*
* 带缓冲区的流中的特殊方法:
* readLine():逐行读取
* newLine():写出回车换行符
*/
public static void main(String[] args) throws IOException {
// demo1();
// demo2();
} public static void demo2() throws FileNotFoundException, IOException {
BufferedReader br = new BufferedReader(new FileReader("zzz.txt")); // 创建带缓冲的字符流
BufferedWriter bw = new BufferedWriter(new FileWriter("aaa.txt")); String lineString;
while ((lineString = br.readLine()) != null) {
bw.write(lineString);
//bw.write("\r\n");
bw.newLine(); // newLine 和 \r\n 的区别是:前者是跨平台的,而后者仅在windows代表换行
} br.close(); // 关流
bw.close();
} public static void demo1() throws FileNotFoundException, IOException {
BufferedReader br = new BufferedReader(new FileReader("zzz.txt")); // 创建带缓冲的字符流
String lineString; while ((lineString = br.readLine()) != null) { // 逐行读取
System.out.println(lineString);
}
br.close(); // 关流
}
}

ReadLine

将文本反转

* 将一个文本文档上的文本反转,第一行和倒数第一行交换,第二行和倒数第二行交换

package com.heima.test;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList; public class Test1 {
/*
* 分析:
* 1、创建输入输出流对象
* 2、创建集合对象,把数据进行临时存储
* 3、将读到的数据存储在集合中
* 4、倒着遍历集合,将数据写到文件上
* 5、关流
*
* 注意事项:流对象尽量晚开早关
*/
public static void main(String[] args) throws IOException {
ArrayList<String> list = new ArrayList<String>(); // 创建空列表
String lineString;
BufferedReader br = new BufferedReader(new FileReader("zzz.txt")); // 创建带缓冲的字符流 while ((lineString = br.readLine()) != null) { // 从文件中逐行读取
list.add(lineString); // 逐行存入列表中
}
br.close(); // 关流1 //Collections.reverse(list); // 也可以调用集合工具类先反转,再正着遍历
BufferedWriter bw = new BufferedWriter(new FileWriter("revzzz.txt"));
for (int i = list.size() - 1; i >= 0; i--) { // 倒着遍历列表
bw.write(list.get(i)); // 通过索引获取列表元素并写入文件中
bw.newLine(); // 换行
}
bw.close(); // 关流2
}
}

Test1

LineNumberReader

* LineNumberReader是BufferedReader的子类,具有相同的功能,并且可以统计行号
  * 调用 getLineNumber()方法可以获取当前行号
  * 调用 setLineNumber()方法可以设置当前行号

package com.heima.chario;

import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader; public class Demo5_LineNumberReader { public static void main(String[] args) throws IOException {
LineNumberReader lnr = new LineNumberReader(new FileReader("zzz.txt")); String lineString;
lnr.setLineNumber(100); // 设置初始的行号,默认为0,每readLine一次,行号就加一
while ((lineString = lnr.readLine())!=null) {
System.out.println(lnr.getLineNumber() + ":" + lineString);
}
lnr.close();
}
}

LineNumberReader

装饰设计模式

package com.heima.chario;

public class Demo6_Wrap {
/*
* 装饰设计模式的好处是:
* 耦合性低,被装饰类的变化与装饰类的变化无关
*/
public static void main(String[] args) {
HeiMaStudent hms = new HeiMaStudent(new Student());
hms.code();
}
} interface Coder {
public void code(); // 定义抽象方法
} class Student implements Coder { @Override
public void code() {
System.out.println("javase");
System.out.println("javaweb");
} } class HeiMaStudent implements Coder { // 目标是装饰Student类,对其进行强化
// 获取被装饰类的引用
private Student student; // 获取学生引用 // 在构造方法中传入被装饰类的对象
public HeiMaStudent(Student s) {
this.student = s;
} // 对原有的功能进行升级
@Override
public void code() {
student.code();
System.out.println("ssh");
System.out.println("数据库");
System.out.println("hadoop");
System.out.println("...");
} }

Wrap

使用指定的码表读写字符

* FileReader是使用默认码表读取文件,如果需要使用指定码表读取,那么可以使用InputStreamReader(字节流,编码表)

* FileWriter是使用默认码表写文件,如果需要使用指定码表写出,那么可以使用OutputStreamReader(字节流,编码表)

package com.heima.chario;

import java.io.*;

public class Demo7_TransIO {

    public static void main(String[] args) throws IOException {
// demo1();
// demo2();
// demo3();
} public static void demo3() throws UnsupportedEncodingException, FileNotFoundException, IOException {
// 采用带缓冲的字符流,进行更高效的读写,装饰设计模式的思想
BufferedReader br = new BufferedReader
(new InputStreamReader(new FileInputStream("utf-8.txt"), "utf-8")); // 创建带缓冲的字符流,关联转换流
BufferedWriter bw = new BufferedWriter
(new OutputStreamWriter(new FileOutputStream("gbk.txt"), "gbk")); int len;
while ((len = br.read())!= -1) { // 使用内置的缓冲区读取数据
bw.write(len);
} br.close(); // 关流
bw.close();
} public static void demo2() throws UnsupportedEncodingException, FileNotFoundException, IOException {
// 指定码表读和写字符
InputStreamReader isr = new InputStreamReader(new FileInputStream("utf-8.txt"),"utf-8"); // 创建字符转换流,关联字节流
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("gbk.txt"),"gbk"); // 编码形式可以省略,省略默认为项目的编码表 int c;
while ((c = isr.read())!= -1) { // 逐个字符读取
osw.write(c);
} isr.close();
osw.close();
} public static void demo1() throws FileNotFoundException, IOException {
// 用默认编码表读写,出现乱码
FileReader fr = new FileReader("utf-8.txt"); // 内容由utf-8编码
FileWriter fw = new FileWriter("gbk.txt"); // 内容由gbk编码 int c;
while ((c = fr.read()) != -1) {
fw.write(c);
} fr.close();
fw.close();
}
}

InputStreamReader

获取文本上字符出现的次数

* 获取文本上每个字符出现的次数,将结果写在 times.txt上

package com.heima.test;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.TreeMap; public class Test2 {
/*
* 分析:
* 1、创建带缓冲的输入流对象
* 2、创建双列集合对象TreeMap
* 3、将读到的字符存储在双列集合中,存储的时候要做判断,如果不包含这个键,就将键和1存储,如果包含这个键,就将键和值+1存储
* 4、关闭输入流,创建输出流对象
* 5、遍历集合,将集合的内容写到times.txt中
* 6、关闭输出流
*/
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("zzz.txt")); //创建带缓冲的输入流对象
TreeMap<Character, Integer> tm = new TreeMap<Character, Integer>(); // 创建双列集合 int c;
while ((c = br.read())!= -1) { // 从文件中逐个读取字符
char ch = (char)c; // 向下强转
/*if (!tm.containsKey(ch)) {
tm.put(ch, 1);
}else {
tm.put(ch, tm.get(ch)+1);
}*/
tm.put(ch, !tm.containsKey(ch)? 1 : tm.get(ch)+1); // 将字符及其出现次数存储到双列集合中
}
br.close(); // 关闭输入流 BufferedWriter bw = new BufferedWriter(new FileWriter("test.txt")); // 创建输出流对象
for (Character key : tm.keySet()) { // 遍历键的集合,获取每个键
/*if (key == '\r') {
bw.write("\\r" + "=" + tm.get(key));
bw.newLine();
} else if (key == '\n') {
bw.write("\\n" + "=" + tm.get(key));
bw.newLine();
}else if (key == '\t') {
bw.write("\\t" + "=" + tm.get(key));
bw.newLine();
}else {
bw.write(key + "=" + tm.get(key));
bw.newLine();
}*/ switch (key) { // 将集合中的内容写到文件中
case '\t': {
bw.write("\\t" + "=" + tm.get(key));
break;
}
case '\r': {
bw.write("\\r" + "=" + tm.get(key));
break;
}
case '\n': {
bw.write("\\n" + "=" + tm.get(key));
break;
} default:
bw.write(key + "=" + tm.get(key));
}
bw.newLine(); // 输入换行
} bw.close(); // 关闭输出流
}
}

Test2

试用版软件

* 当我们下载一个试用版软件时,每执行一次就会提醒我们还有多少次使用的机会
* 用IO知识,模拟试用版软件,试用10次,每执行一次, 提示一次还剩几次机会,如果次数到了,就提示:请购买正版

package com.heima.test;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException; public class Test3 {
/*
* 分析:
* 1、创建待缓冲的输入流对象,使用readLine()方法,保证数据的原样性
* 2、将读到的字符串转换为int数
* 3、对int数进行判断,如果大于0,就将其减一,并写回源文件;如果小于等于0,就提示"请购买正版软件"
*
*/
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("config.txt"));
String line = br.readLine(); // 整行读取
int c = Integer.parseInt(line); // 将字符串型数字转换为int型数字
br.close(); // 关闭输入流 FileWriter fw = new FileWriter("config.txt"); // 会清空config.txt文件
if (c > 0) {
System.out.println("您还有 " + c-- + "次机会");
fw.write(c + ""); // 打印字符串
} else {
System.out.println("试用次数以耗尽,请购买正版");
fw.write(0 + ""); // 将0写回文件,否则config.txt就是空的了
} fw.close(); // 关闭输出流,如果忘记关流,数据在缓冲区内不会被刷过去 }
}

Test3

递归

* 递归的弊端:不能调用太多次,容易导致栈溢出
* 递归的好处:不用知道循环次数

* 练习:从键盘输入接收一个文件夹路径,打印出该文件夹下所有的 .java文件

package com.heima.test;

import java.io.File;
import java.util.Scanner; public class Test4 {
/*
* 分析:
* 1、从键盘接收一个文件夹路径
* 如果录入的是不存在的,给提示
* 如果录入的是文件路径,也给提示
* 如果是文件夹路径,直接返回
*
* 2、获取到该文件夹下的所有文件和文件夹,存储在一个file数组中
*
* 3、遍历数组,对每一个文件或文件夹做判断,
* 如果是文件,并且后缀是.java就打印;
* 如果是文件夹,就递归调用
*
* 注意:构造方法不能递归调用
*/ public static void main(String[] args) {
File dir = getDir(); // 获取文件夹路径
printJavaFile(dir); // 调用递归方法 } /*
* 获取键盘录入的文件夹路径
* 1、返回值类型,File
* 2、不需要参数
*/
public static File getDir() {
Scanner sc = new Scanner(System.in); // 创建键盘录入对象
System.out.println("请输入一个文件夹路径"); // 提示输入
while (true) { // 定义无限循环
String liString = sc.nextLine(); // 将键盘录入的文件夹路径存储
File dir = new File(liString); // 将录入的内容封装成File对象
if (!dir.exists()) { // 对File对象进行一系列判断
System.out.println("您录入的文件夹路径不存在,请重新录入");
} else if (dir.isFile()) {
System.out.println("您录入的是文件路径,请您录入文件夹路径");
} else {
sc.close();
return dir; // 返回File对象
}
}
}
/*
* 获取文件夹路径下的所有.java文件
* 1、返回值为void
* 2、参数列表为File dir
*/
public static void printJavaFile(File dir) { // 传入文件夹路径
File[] subFiles = dir.listFiles(); // 获取该路径下所有的文件和文件夹
for (File subfile : subFiles) { // 遍历File数组
if (subfile.isFile() && subfile.getName().endsWith(".java")) { // 判断是否符合条件
System.out.println(subfile.getName()); // 如果符合,就打印
} else if (subfile.isDirectory()) { // 如果是文件夹
printJavaFile(subfile); // 递归调用
}
}
}
}

Test4

Java I/O流 03的更多相关文章

  1. Java虚拟机JVM学习03 连接过程:验证、准备、解析

    Java虚拟机JVM学习03 连接过程:验证.准备.解析 类被加载后,就进入连接阶段. 连接就是将已经读入到内存的类的二进制数据合并到虚拟机的运行时环境中去. 连接阶段三个步骤:验证.准备和解析. 类 ...

  2. Java IO: 字符流的Piped和CharArray

    作者: Jakob Jenkov 译者: 李璟(jlee381344197@gmail.com) 本章节将简要介绍管道与字符数组相关的reader和writer,主要涉及PipedReader.Pip ...

  3. day36-IO流03

    JavaIO流03 4.常用的类02 4.4节点流和处理流 4.4.1基本介绍 节点流可以从一个特定的数据源读写数据,如FileReader.FileWriter 数据源就是存放数据的地方,比如文件. ...

  4. 【转】输入/输出流 - 深入理解Java中的流 (Stream)

    基于流的数据读写,太抽象了,什么叫基于流,什么是流?Hadoop是Java语言写的,所以想理解好Hadoop的Streaming Data Access,还得从Java流机制入手.流机制也是JAVA及 ...

  5. 理解Java中字符流与字节流的区别

    1. 什么是流 Java中的流是对字节序列的抽象,我们可以想象有一个水管,只不过现在流动在水管中的不再是水,而是字节序列.和水流一样,Java中的流也具有一个“流动的方向”,通常可以从中读入一个字节序 ...

  6. Java Io 字符流

    Java Io 字符流包含: 1. InputStreamReader  它是由byte流解析为char流,并且按照给定的编码解析. 2. OutputStreamWrite  它是char流到byt ...

  7. mybatis oracle java.sql.SQLException: 流已被关闭问题

    /** * 按照页码取值(从current_page页开始,每页page_size条) * @param key * @param params * @param current_page * @pa ...

  8. Java IO包装流如何关闭?

      问题: (1)JAVA的IO流使用了装饰模式,关闭最外面的流的时候会自动调用被包装的流的close()方吗? (2)如果按顺序关闭流,是从内层流到外层流关闭还是从外层到内存关闭? 问题(1)解释: ...

  9. java 笔记(4) —— java I/O 流、字节流、字符流

    Java中使用流来处理程序的输入和输出操作,流是一个抽象的概念,封装了程序数据于输入输出设备交换的底层细节.JavaIO中又将流分为字节流和字符流,字节流主要用于处理诸如图像,音频视频等二进制格式数据 ...

随机推荐

  1. hdu5433 Xiao Ming climbing

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission ...

  2. Codeforces Round #670 (Div. 2) B. Maximum Product (暴力)

    题意:有一长度为\(n\)的序列,求其中任意五个元素乘积的最大值. 题解:先排序,然后乘积能是正数就搞正数,模拟一下就好了. 代码: int t; ll n; ll a[N]; int main() ...

  3. AtCoder Beginner Contest 179 E - Sequence Sum (模拟)

    题意:\(f(x,m)\)表示\(x\ mod\ m\),\(A_{1}=1\),而\(A_{n+1}=f(A^{2}_{n},M)\),求\(\sum^{n}_{i=1}A_{i}\). 题解:多算 ...

  4. win7 & centos7 双系统安装方法

    1.准备 1)Centos7镜像 官方:https://www.centos.org/ 阿里镜像:http://mirrors.aliyun.com/centos/ 2)安装windows7系统的电脑 ...

  5. C# 通过Internet搜索网络资源

    Internet 网络资源非常丰富,几乎涉及到日常生活和研究的各个方面.流行的搜索引擎像Google.百度.雅虎等都能完成快速搜索网络资源的功能.本节我们将学习用C#实现这些功能的基本思路. 在Sys ...

  6. 6.Header交换机之模拟验证用户身份

    标题 : 6.Header交换机之模拟验证用户身份 目录 : RabbitMQ 序号 : 6 var channel = connection.CreateModel(); ​ //设置服务质量 ch ...

  7. 编写一个c函数,该函数给出一个字节中被置为1的位的个数

    请编写一个c函数,该函数给出一个字节中被置为1的位的个数 #include <stdio.h> void fun(char ch) { int i; int temp; int count ...

  8. confirm() :带有指定消息和 OK 及取消按钮的对话框

    定义和用法 confirm() 方法用于显示一个带有指定消息和 OK 及取消按钮的对话框. 语法 confirm(message) 参数描述 message 要在 window 上弹出的对话框中显示的 ...

  9. windows脚本bat编程:WIN10脚本自动启动虚拟环境中的jupyter

    python编程对各种扩展包的版本依赖较严格,为了解决版本差异,通用情况下会使用virtualenv创建的虚拟环境来独立应用.那么每次使用的时候就需要启动虚拟环境,如果每次都是手工启动,每次输入几条命 ...

  10. css sticky & 吸顶效果

    css sticky & 吸顶效果 demo https://codepen.io/xgqfrms/pen/PoqyVYz css position sticky not working ht ...