JAVA中文件的读写 I/O 输入输出流
Posted 初心不变1
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA中文件的读写 I/O 输入输出流相关的知识,希望对你有一定的参考价值。
主要内容
1.编码问题
2.File类的使用
3.RandomAccessFile的使用
4.I/O 输入输出流
编码问题:
1 import java.io.UnsupportedEncodingException; 2 3 public class 编码问题 { 4 public static void main(String[] args) { 5 // 我们项目的默认编码是GBK 6 String s = "测试 ABC"; 7 byte[] byte1 = s.getBytes();// 转换成的字节序列用的是项目默认的编码gbk 8 for (byte b : byte1) { 9 // 1 byte = 8 位 //toHexString这个函数是把字节(转换成了Int)以16进制的方式显示 10 System.out.print(Integer.toHexString(b & 0xff) + " ");// & 11 // 0xff是为了把前面的24个0去掉只留下后八位 12 } 13 14 try { 15 // 也可以转换成指定的编码 16 byte[] bytes1 = s.getBytes("gbk"); 17 System.out.println(new String(bytes1)); 18 } catch (UnsupportedEncodingException e) { 19 // TODO Auto-generated catch block 20 e.printStackTrace(); 21 } 22 /** 23 * gbk编码: 中文占用两个字节,英文占用一个字节 utf-8编码:中文占用三个字节,英文占用一个字节 24 * java是双字节编码,是utf-16be编码 utf-16be编码:中文占用两个字节,英文占用两个字节 25 * 当你的字节序列是某种编码时,这个时候想把字节序列变成字符串,也需要用这种编码方式,否则会出现乱码 26 */ 27 try { 28 byte[] byte2 = s.getBytes("utf-16be"); 29 String s2 = new String(byte2, "utf-16be"); 30 System.out.println(s2); 31 } catch (UnsupportedEncodingException e) { 32 // TODO Auto-generated catch block 33 e.printStackTrace(); 34 } 35 /** 36 * 文本文件就是字节序列,可以是任意编码的字节序列 37 * 如果我们在中文机器上直接创建文本文件,那么该文件只认识ANSI编码(例如直接在电脑中创建文本文件) 38 */ 39 40 /** 41 * byte转int的时候为什么非要先&0xff计算出来才是正确答案? 42 * 首先,java中的二进制采用的是补码形式,并非原码或反码,这3个概念要搞清楚; 43 * 其次,byte占8位,int占32位,将byte强制转换为int型时,如果没有做 & 44 * 0xff运算,且byte对应的值为负数的话,就会对高位3个字节进行补位,这样就有可能出现补位误差的错误。 45 * 举例来说,byte型的-1,其二进制(补码)为11111111(即0xff),转换成int型,值也应该为-1,但经过补位后, 46 * 得到的二进制为11111111111111111111111111111111(即0xffffffff),这就不是-1了,对吧? 47 * 而0xff默认是int型,所以,一个byte跟0xff相与,会先将那个byte转化成int型运算,这样,结果中的高位3个字节就总会被清0, 48 * 于是结果就是我们想要的了~ 49 */ 50 51 } 52 53 }
File类的使用:
1 import java.io.File; 2 import java.io.IOException; 3 4 public class FileDemo { 5 6 /** 7 * @param args 8 */ 9 public static void main(String[] args) { 10 // 了解构造函数的情况 查帮助ALT+/ 11 File file = new File("E:\\\\javaio\\\\imooc"); 12 // 判断文件/文件夹是否存在 13 // System.out.println(file.exists()); 14 if (!file.exists()) 15 file.mkdir(); // file.mkdirs()如果文件不存在,直接创建文件夹 16 // mkdir创建的一级目录,如果需要创建多级目录可以使用mkdirs() 17 else 18 file.delete(); 19 20 // 是否是一个目录 如果是目录返回true,如果不是目录or目录不存在返回的是false 21 System.out.println(file.isDirectory()); 22 // 是否是一个文件 23 System.out.println(file.isFile()); 24 25 // File file2 = new File("e:\\\\javaio\\\\日记1.txt"); 26 File file2 = new File("e:\\\\javaio", "日记1.txt"); 27 if (!file2.exists()) 28 try { 29 file2.createNewFile(); 30 } catch (IOException e) { 31 // TODO Auto-generated catch block 32 e.printStackTrace(); 33 } 34 else 35 file2.delete(); 36 // 常用的File对象的API 37 System.out.println(file);// file.toString()的内容 38 System.out.println(file.getAbsolutePath()); 39 System.out.println(file.getName()); 40 System.out.println(file2.getName()); 41 System.out.println(file.getParent()); 42 System.out.println(file2.getParent()); 43 System.out.println(file.getParentFile().getAbsolutePath()); 44 } 45 46 }
遍历目录
1 import java.io.File; 2 import java.io.IOException; 3 4 //列出File的一些常用操作比如过滤,遍历等操作 5 public class FileUtils { 6 /** 7 * 列出指定指定目录下(包括其子目录)的所有文件 8 * 9 * @param dir 10 * @throws IOException 11 */ 12 public static void listDirectory(File dir) throws IOException { 13 if (!dir.exists()) { 14 throw new IllegalArgumentException("目录:" + dir + "不存在"); 15 } 16 if (!dir.isDirectory()) { 17 throw new IllegalArgumentException(dir + "不是目录"); 18 } 19 20 // String[] fileNames = 21 // dir.list();//返回的是字符串数组,list()方法用于列出当前目录下的子目录和文件,直接子的名称,不包含子目录下的内容 22 // for (String string : fileNames) { 23 // System.out.println(dir+"\\\\"+string); 24 // } 25 // 26 // 如果要遍历子目录下的内容就需要构造成File对象做递归操作,File提供了直接返回File对象的API 27 File[] files = dir.listFiles();// 返回的是直接子目录(文件)的抽象 28 if (files != null && files.length > 0) {// 确定存在子目录 29 for (File file : files) { 30 if (file.isDirectory()) { 31 // 递归 32 listDirectory(file); 33 } else { 34 System.out.println(file); 35 } 36 } 37 } 38 } 39 }
RandomAccessFile的使用
1 import java.io.File; 2 import java.io.IOException; 3 import java.io.RandomAccessFile; 4 import java.util.Arrays; 5 6 public class RafDemo { 7 8 /** 9 * @param args 10 */ 11 public static void main(String[] args) throws IOException { 12 File demo = new File("demo"); 13 if (!demo.exists()) 14 demo.mkdir(); 15 File file = new File(demo, "raf.dat"); 16 if (!file.exists()) 17 file.createNewFile(); 18 19 RandomAccessFile raf = new RandomAccessFile(file, "rw"); 20 // 指针的位置 21 System.out.println(raf.getFilePointer()); 22 23 raf.write(\'A\');// 只写了一个字节 24 System.out.println(raf.getFilePointer()); 25 raf.write(\'B\'); 26 27 int i = 0x7fffffff; 28 // 用write方法每次只能写一个字节,如果要把i写进去就得写4次 29 raf.write(i >>> 24);// 高8位 30 raf.write(i >>> 16); 31 raf.write(i >>> 8); 32 raf.write(i); 33 System.out.println(raf.getFilePointer()); 34 35 // 可以直接写一个int 36 raf.writeInt(i); 37 38 String s = "中"; 39 byte[] gbk = s.getBytes("gbk"); 40 raf.write(gbk); 41 System.out.println(raf.length()); 42 43 // 读文件,必须把指针移到头部 44 raf.seek(0); 45 // 一次性读取,把文件中的内容都读到字节数组中 46 byte[] buf = new byte[(int) raf.length()]; 47 raf.read(buf); 48 49 System.out.println(Arrays.toString(buf)); 50 for (byte b : buf) { 51 System.out.println(Integer.toHexString(b & 0xff) + " "); 52 } 53 raf.close(); 54 } 55 56 }
import java.io.IOException; import java.io.RandomAccessFile; public class RafReadDemo { /** * @param args */ public static void main(String[] args) throws IOException { // TODO Auto-generated method stub RandomAccessFile raf = new RandomAccessFile("demo/raf.dat", "r"); raf.seek(2); int i = 0; int b = raf.read();// 读取到一个字节 System.out.println(raf.getFilePointer()); i = i | (b << 24); b = raf.read(); i = i | (b << 16); b = raf.read(); i = i | (b << 8); b = raf.read(); i = i | b; System.out.println(Integer.toHexString(i)); raf.seek(2); i = raf.readInt(); System.out.println(Integer.toHexString(i)); raf.close(); } }
1 import java.io.File; 2 import java.io.IOException; 3 import java.io.RandomAccessFile; 4 public class RandomAccessFileSeriaDemo { 5 6 /** 7 * @param args 8 */ 9 public static void main(String[] args) throws IOException { 10 // TODO Auto-generated method stub 11 File demo = new File("demo1"); 12 if (!demo.exists()) 13 demo.mkdir(); 14 File file = new File(demo, "raf.dat"); 15 if (!file.exists()) 16 file.createNewFile(); 17 // 打开文件,进行随机读写 18 RandomAccessFile raf = new RandomAccessFile(file, "rw"); 19 /* 序列化 */ 20 int i = 0x7ffffff; 21 raf.write(i >>> 24); 22 raf.write(i >>> 16); 23 raf.write(i >>> 8); 24 raf.write(i); 25 System.out.println(raf.getFilePointer()); 26 27 /* 反序列化 */ 28 raf.seek(0); 29 int b = raf.read(); 30 i = i | (b << 24); 31 b = raf.read(); 32 i = i | (b << 16); 33 b = raf.read(); 34 i = i | (b << 8); 35 b = raf.read(); 36 i = i | b; 37 System.out.println(Integer.toHexString(i)); 38 raf.close(); 39 } 40 } 41 42 RandomAccessFileSeriaDemo
I/O 输入输出流
流的定义:
流就是程序和设备之间嫁接起来的一根用于数据传输的管道,这个管道上有很多按钮,不同的按钮可以实现不同的功能。
这根用于数据传输的管道就是流,流就是一根管道
输入时,程序在源(文件,网络,内存)上打开一个流,然后如图一个一个顺序读。写也一样。
流的分类和使用:
四大基本抽象流,文件流,缓冲流,转换流,数据流,Print流,Object流。
JAVA.io 包中定义了多个流类型(类或抽象类)来实现输入/输出功能;可以从不同角度对其进行分类:
*按数据流的方向不用可以分为输入流和输出流
*按处理数据单位不同可以分为字节流和字符流
*按照功能不同可以分为节点流和处理流
JAVA中所提供的的所有流类型位于包JAVA.io内,都分别继承自以下四种抽象流类型:
节点流与处理流:
节点流可以从一个特定的数据源(节点)读取数据(如:文件,内存)
处理流是“连接”在已存在的流(节点流或处理流)之上,通过对数据的处理为程序提供更为强大的读写功能。
节点流也叫原始流,处理流也叫包裹流。
流与类的关系:
如果一个类是用作设备和程序之间的数据传输,则这个类有一个新的名字叫做流
流一定是类,但类不一定是流
四大基本流的介绍
输入流,输出流,字节流,字符流
InputStream和OutputStream读写数据的单位是一个字节
Reader和Writer读写数据的单位是一个字符
在JAVA中一个字符占两个字节
InputStream,OutputStream,Reader,Writer都是抽象类,或者说都是抽象流,通常我们使用的都是它们的子类,凡是以Stream结尾的都是字节流。
InputStream 流中的常用方法:
OutputStream 流中的常用方法:
Reader 流中的常用方法:
Writer 流中的常用方法:
文件流
文件流包括:
FileInputStream FileOutputStream --字节流
FileReader FileWriter --字符流
实例:读取一个文件的内容并将其输出到显示器上,并统计读取的字节个数
1 /* 2 利用FileReader流来读取一个文件中的数据,并在显示器上输出! 3 */ 4 5 import java.io.*; 6 7 public class TestFileReader { 8 public static void main(String[] args) { 9 FileReader fr = null; 10 11 try { 12 fr = new FileReader("C:\\\\Documents and Settings\\\\others\\\\桌面\\\\java\\\\TestFileReader.java"); 13 int cnt = 0; 14 int ch; 15 16 while (-1 != (ch = fr.read())) // 20行 17 { 18 System.out.print((char) ch); // System.out.print(int ch); 19 // 这是在显示器上输出ch的整数值,所以必须的进行类型转化,我们需要输出的是ch所代表的整数对应的字符 20 ++cnt; 21 } 22 23 System.out.printf("总共从TestFileReader.java文件中读取了%d个字符", cnt); 24 } catch (FileNotFoundException e) { 25 System.out.println("找不到文件!"); 26 System.exit(-1); 27 } catch (IOException e) { 28 System.out.println("文件读取失败!"); 29 System.exit(-1); 30 } 31 } 32 }
FileInputStream的使用
FileReader的使用
字节流与字符流的区别:
FileInputStream 和FileOutputStream 可以完成所有格式文件的复制
FileReader和FileWriter只可以完成文本文件的复制,却无法完成其他格式文件的复制
因为字节是不需要解码和编码的,将字节转化为字符才存在解码和编码的问题
字节流可以从所有格式的设备中读写数据,但字符流只能从文本格式的设备中读写数据
实例:编程实现文件的复制
1 /* 2 利用FileInputStream 和 FileOutputStream 可以完成所有格式文件的赋值 3 因为字节是不需要解码和编码的,将字节转化为字符才存在解码的问题 4 本程序完成了音频文件的复制 5 */ 6 7 import java.io.*; 8 9 public class TestFileInputStreamOutputStreamCopy { 10 public static void main(String[] args) { 11 FileInputStream fi = null; 12 FileOutputStream fo = null; 13 14 try { 15 fi = new FileInputStream("E:\\\\综艺\\\\歌曲\\\\卡农.mp3"); 16 fo = new FileOutputStream("d:/share/Output.txt"); //使用播放器可正常播放该文件 17 int ch; 18 19 while (-1 != (ch = fi.read())) { 20 fo.write(ch); 21 } 22 } catch (FileNotFoundException e) { 23 System.out.println("文件没有找到!"); 24 System.exit(-1); 25 } catch (IOException e) { 26 System.out.println("文件读写错误!"); 27 System.exit(-1); 28 } finally { 29 try { 30 if (null != fi) { 31 fi.close(); 32 fi = null; 33 } 34 if (null != fo) { 35 fo.close(); 36 fo = null; 37 } 38 } catch (Exception e) { 39 e.printStackTrace(); 40 System.exit(-1); 41 } 42 } 43 44 System.out.println("文件复制成功!"); 45 } 46 }