Java字符字节IO
IO流
字节输入流——FileInputStream
作用:以内存为基准,把磁盘文件中的数据按照字节的形式读入到内存中的流
方法
public FileInputStream(File path):创建一个字节输入流管道与源文件对象接通
public FileInputStream(String pathName):创建一个字节输入流管道与文件路径对接
public int read():每次读取一个字节返回,读取完毕后返回-1
一个一个读取字节
/** * 禁止使用次方案,读取英文字幕没问题,但读取中文(二字节)会截断,且性能较差 */ // 1.创建一个字节输入流管道与源文件接通 InputStream is = new FileInputStream("字节流/src/dlei01.txt"); // 2.读取一个字节的编号返回,读取完毕返回-1 int ch = 0; while ((ch = is.read()) != -1) { System.out.println((char)ch); }
一个一个读取字节数组
/** * 使用字节数组读取内容,效率可以,但仍无法避免中文输出乱码 */ InputStream is = new FileInputStream("字节流/src/dlei01.txt"); // 定义一个字节数组读取数据 byte[] buffer = new byte[3]; int len; while((len = is.read(buffer)) != -1) { String rs = new String(buffer, 0, len); System.out.println(rs); }
解决以上读取中文乱码的方案——只适合小文件,否则内存可能溢出
/** * 定义一个与文件大小一样大的字节数组 */ File f = new File("字节流/src/dlei01.txt"); InputStream is = new FileInputStream(f); // 定义一个字节数组读取数据 byte[] buffer = new byte[(int) f.length()]; int len = is.read(buffer); String rs = new String(buffer); System.out.println(rs);
总结:字节流不适合读取文本文件内容输出,读写文件内容建议使用字符流
FileOutputStream文件字节输出流
作用:以内存为基准,把内存中的数据,按照字节的形式写出到磁盘文件中去
public static void main(String[] args) throws IOException { // 1.创建一个文件对象定位目标文件(写数据到文件,文件会自动创建) // File file = new File("src/dlei04.txt"); // // 2.创建一个字节输出流管道与目标文件对象接通 // OutputStream os = new FileOutputStream(file); // 3. 简化写法:创建一个字节输出流管道与目标文件路径接通, 默认是数据覆盖管道 //OutputStream os = new FileOutputStream("src/dlei04.txt"); // 第二个参数为true,则为追加数据管道 OutputStream os = new FileOutputStream("src/dlei04.txt", true); // 4.写数据出去 // a.写一个字节出去 os.write(97); os.write('b'); // os.write('磊'); // 只会写出中文的第一个字节,写出去就乱码 os.write("\r\n".getBytes()); // 换行兼容更好 // b.写一个字节数组出去 byte[] bytes = new byte[]{48, 49, 50, 56, 54, 59}; os.write(bytes); byte[] bytes1 = "Java是最优美的语言".getBytes(); // 默认以当前编码UTF-8提取字节数 os.write(bytes1); os.write("\r\n".getBytes()); // 换行兼容更好 byte[] bytes2 = "Java是最优美的语言".getBytes(); // 默认以当前编码UTF-8提取字节数 os.write(bytes2, 0, 19); os.flush(); // 立即刷新数据到文件中去,刷新后管道可以继续使用 os.close(); // 关闭资源管道,关闭包含了刷新,关闭后管道不能使用了 }
字节流做文件复制
public class CopyDemo { public static void main(String[] args) { InputStream is = null; OutputStream os = null; try { // 1.创建一个字节输入管道与源文件接通 is = new FileInputStream("字节流做文件复制/src/test.txt"); // 2.创建一个字节输出流与目标文件接通 os = new FileOutputStream("字节流做文件复制/src/test1.txt"); // 3.创建一个桶 byte[] buffer = new byte[1024]; //1kb // 4.从字节输入流管道中读取数据,写出到字节输出流管道 int len; while ((len = is.read(buffer)) != -1) { os.write(buffer, 0, len); } } catch (Exception e) { e.printStackTrace(); } finally { if (is != null) { try { is.close(); } catch (Exception e) { e.printStackTrace(); } } if (os != null) { try { os.close(); } catch (Exception e) { e.printStackTrace(); } } } } }
JDK1.7后资源释放新方式
public static void main(String[] args) { try( // 1.创建一个字节输入管道与源文件接通 InputStream is = new FileInputStream("字节流做文件复制/src/test.txt"); // 2.创建一个字节输出流与目标文件接通 OutputStream os = new FileOutputStream("字节流做文件复制/src/test1.txt"); ) { // 3.创建一个桶 byte[] buffer = new byte[1024]; //1kb // 4.从字节输入流管道中读取数据,写出到字节输出流管道 int len; while ((len = is.read(buffer)) != -1) { os.write(buffer, 0, len); } } catch (Exception e) { e.printStackTrace(); }
FileReader文件字符输入流
public class FileReaderDemo { public static void main(String[] args) throws Exception{ // // 1.创建一个文件对象定位源文件 // File f = new File("字符流/src/test.txt"); // // 2.创建一个字符输入流管道与源文件接通 // Reader fr = new FileReader(f); // 3.简化写法:创建一个字符输入流管道与源文件路径接通 Reader fr = new FileReader("字符流/src/test.txt"); // 4.按照字符读取,每次读取一个字符的编号返回 // int code1 = fr.read(); // System.out.println((char) code1); int ch; while ((ch=fr.read()) != -1) { System.out.println((char) ch); } /** * 字符流按照字符数组循环读取数据,抗原解决中文读取输出乱码的问题,而且性能也较好! */ // 1.创建一个文件对象定位源文件 Reader fr2 = new FileReader("字符流/src/test.txt"); // 2.按照字符数组读取内容 // char[] buffer = new char[3]; // int len = fr2.read(buffer); // System.out.println("字符数:" + len); // String rs = new String(buffer); char [] buffer = new char[1024]; int len; while ((len = fr2.read(buffer)) != -1) { // 读取多少倒出多少字符 System.out.println(new String(buffer, 0, len)); } } }
FileWriter文件字符输出流
public class FileWriterDemo { public static void main(String[] args) throws Exception{ // 1.创建一个字符输出流管道通向目标文件路径 // Writer fw = new FileWriter("字符流/src/test1.txt"); // 覆盖数据管道 Writer fw = new FileWriter("字符流/src/test1.txt", true); // 追加数据管道 // 2. 写一个字符出去 fw.write(97); fw.write('c'); fw.write('呵'); fw.write("\r\n"); fw.write("Java是最优美的语言"); fw.write("\r\n"); fw.write("我爱中国".toCharArray()); fw.write("\r\n"); fw.write("Java是最优美的语言", 0, 9); fw.write("\r\n"); fw.write("我爱中国".toCharArray(), 0, 2); fw.close(); } }
缓冲流
缓冲流可以提高字节流和字符流的读写数据的性能
BufferedInputStream字节缓冲输入流
public class BufferedInputStreamDemo { public static void main(String[] args) throws Exception{ // 1.定义一个低级的字节输入流与源文件接通 InputStream is = new FileInputStream("字符流/src/test.txt"); // 3.把低级的字节输入流包装成一个高级的缓冲字节输入流 BufferedInputStream bis = new BufferedInputStream(is); // 2.定义一个字节数组读取数据 byte[] buffer = new byte[3]; int len; while((len = bis.read(buffer)) != -1) { String rs = new String(buffer, 0, len); System.out.println(rs); } } }
BufferedOutputStream字节缓冲输出流
OutputStream os = new FileOutputStream("字符流/src/test1.txt"); BufferedOutputStream bos = new BufferedOutputStream(os); // 4.写数据出去 // a.写一个字节出去 bos.write(97); bos.write('b'); // os.write('磊'); // 只会写出中文的第一个字节,写出去就乱码 bos.write("\r\n".getBytes()); // 换行兼容更好 bos.close();
BufferedReader字符缓冲输入流
Reader fr2 = new FileReader("字符流/src/test.txt"); BufferedReader br = new BufferedReader(fr2); String line; // 使用一个循环读取数据(经典代码),性能好,对业务也更好 while ((line = br.readLine()) != null) { System.out.println(line); } // char [] buffer = new char[1024]; // int len; // while ((len = br.read(buffer)) != -1) { // // 读取多少倒出多少字符 // System.out.println(new String(buffer, 0, len)); // } br.close();
BufferedWriter字符缓冲输出流
Writer fw = new FileWriter("字符流/src/test2.txt"); BufferedWriter bw = new BufferedWriter(fw); bw.write("Java是最优美的语言"); bw.newLine(); bw.write("我爱中国".toCharArray()); bw.newLine(); bw.write("Java是最优美的语言", 0, 9); bw.newLine(); bw.write("我爱中国".toCharArray(), 0, 2); bw.close();
字符流不同编码读取乱码的问题
InputStreamReader字符输入转换流
// 代码:UTF-8 文件:GBK (ab我爱你: o o [oo] [oo] [oo]) InputStream is = new FileInputStream("字符流/src/424.txt"); Reader fr2 = new InputStreamReader(is, "GBK"); // 指定编码把字节流转换成GBK编码格式的字符输入流 BufferedReader br = new BufferedReader(fr2); String line; // 使用一个循环读取数据(经典代码),性能好,对业务也更好 while ((line = br.readLine()) != null) { System.out.println(line); } br.close();
OutputStreamReader字符输出转换流
OutputStream os = new FileOutputStream("字符流/src/test1.txt"); // 把字节流转换成字符输出流 // Writer fw = new OutputStreamWriter(os);// 把字节输出流按照默认编码UTF-8转换成字符输出流 Writer fw = new OutputStreamWriter(os, "GBK"); // 把字节输出流按照编码GBK转换成字符输出流 fw.write("abdc我是中国人"); fw.close();
序列化与反序列化
对象如果想参与序列化,对象必须实现序列化接口 implements Serializable,否则序列化会报错
transient修饰成员变量时,它将不参与序列化
必须序列化使用的版本号和反序列化使用的版本号一致才可以正常反序列化,否则报错
打印流