IO中的常用方法
这张图放这里便于理解:
1、二进制文件的写入和读取
这个即是我们最常用的文件上传下载操作,图片、音乐等类文件的读取。
文件的读写肯定需要先找到文件,而找到文件分很多种,总结如下:
1、获取工程根目录的方法
- new File("").getAbsolutePath();//新建个空文件对象
- System.getProperty(“user.dir”);//使用(JVM)系统的属性
- 获取根目录下面的文件或子目录: new File(“文件名”).getAbsolutePath();文件名前无需斜杠
System.getProperty(“user.dir”)+"/文件名"2、获取classpath根目录的方法(classpath是编译过后的文件(字节码)下的地址)
- 类名.class.getResource("/");
- 类名.class.getClassLoader().getResource("");
- Thread.currentThread().getContextClassLoader().getResource("");//当前线程的类加载器去获取
获取下面的子目录或文件名: 直接在空字符串处加文件或目录名3、获取当前类文件所在目录的方法
- 类名.class.getResource("");
- 找子目录:类名.class.getResource(“子文件名”);
FileInputStream和fileOutputStream的使用
JDK官方文档:(可忽略) 从文件系统中的某个文件中获得输入字节。哪些文件可用取决于主机环境。 FileInputStream 用于读取诸如图像数据之类的原始字节流。要读取字符流,请考虑使用 FileReader。
下面就可以开工了:
我们用txt文件的二进制形式读写来模拟音乐等其他文件的读写:
/**
* 二进制文件的输入,从外部取进来
* @throws IOException
*/
@Test
public void test04() throws IOException {
//new File("").getAbsolutePath()为获取文件路径
FileInputStream fileInputStream = new FileInputStream(new File("io/test.txt").getAbsolutePath());
int c;
// 读取写入的二进制文件,输出字节数组,有三个read方法,但达到文件末都返回-1
while ((c = fileInputStream.read()) != -1) {
System.out.print(c);
/**test.txt中写了两个1,输出结果为:
* 4949
*/
}
}
/**
* 二进制文件的输出,写东西到外部文件
* @throws IOException
*/
@Test
public void test05() throws IOException {
byte[] bytes = {12,21,34,11,21};//新建字节数组
FileOutputStream fileOutputStream = new FileOutputStream(new File("").getAbsolutePath()+"/io/test.txt");
// 写入二进制文件,直接打开会出现乱码
fileOutputStream.write(bytes);
fileOutputStream.close();
}
2、文本文件的写入和读取
文本文件即肉眼能看懂的文件,需要进行统一编码的。
使用FileWriter和FileReader:
JDK官方文档(可忽略): public class FileReaderextends InputStreamReader用来读取字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是适当的。要自己指定这些值,可以先在
FileInputStream 上构造一个 InputStreamReader。 FileReader
用于读取字符流。要读取原始字节流,请考虑使用 FileInputStream。 public class FileWriterextends
OutputStreamWriter用来写入字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是可接受的。要自己指定这些值,可以先在
FileOutputStream 上构造一个 OutputStreamWriter。
文件是否可用或是否可以被创建取决于底层平台。特别是某些平台一次只允许一个
FileWriter(或其他文件写入对象)打开文件进行写入。在这种情况下,如果所涉及的文件已经打开,则此类中的构造方法将失败。
FileWriter 用于写入字符流。要写入原始字节流,请考虑使用 FileOutputStream。
实例如下:
/**
* 读取文本文件
* @throws FileNotFoundException
*/
@Test//不使用缓冲区
public void test09() throws IOException {
FileReader fileReader = new FileReader(new File("").getAbsolutePath()+"/io/test.txt");
int c;
while ((c = fileReader.read()) != -1) {
System.out.print((char) c);
}
}
@Test
public void test08() throws IOException {
FileReader fileReader = new FileReader(new File("").getAbsolutePath()+"/io/test.txt");
//FileReader也有三个read方法:这三个read方法,每次调用一次就会read一次file,进行一次IO。不管是多次read还是一次性的read,都不是很优雅的在read文件的方式。
// BufferedReader缓冲区,它的IO行为是每次读进来8k的数据到缓冲区,要用的时候直接取。
BufferedReader bufferedReader = new BufferedReader(fileReader);
String str;
while ((str = bufferedReader.readLine()) != null) {
System.out.println(str);
}
fileReader.close();
bufferedReader.close();
}
write() 方法和 append() 方法并不是像方法名那样,一个是覆盖内容,一个是追加内容,append() 内部也是 write() 方法实现的,也非说区别,也就是 append() 方法可以直接写 null,而 write() 方法需要把 null 当成一个字符串写入,所以两者并无本质的区别。需要注意的是这里并没有指定文件编码,可能会出现乱码的问题。
3、复制文件,常用的文件上传与下载
首先我提一下下面要用到的字节数组的基础概念,
字节数组就是计算机的最终存储方式,新建一个字节数组有两种方式:
新建一个长为1024(1kb)的字节数组:byte[] bt=new byte[1024];
新建一个字节数组内容为:byte[] bt={11,12,42};
下面read每调用一次就会装入1024,最后次可能不够。
这里演示不使用缓冲流对读写文件的影响,文件的复制实质还是文件的读写。缓冲流是处理流,是对节点流的装饰。
@Test
public void test12() throws IOException {
// 输入和输出都使用缓冲流
FileInputStream in = new FileInputStream("E:\\视频资料\\大数据原理与应用\\1.1大数据时代.mp4");
BufferedInputStream inBuffer = new BufferedInputStream(in);
FileOutputStream out = new FileOutputStream("1.1大数据时代.mp4");
BufferedOutputStream outBuffer = new BufferedOutputStream(out);
int len = 0;//定这里定义个长度,是防止后面数据不足以装满一个字节数组的情况发生,导致多读了一段
byte[] bs = new byte[1024];
long begin = System.currentTimeMillis();
//read(byte[] b):从此输入流中将 byte.length(此处为1024) 个字节的数据读入一个 byte 数组中。
while ((len = inBuffer.read(bs)) != -1) {
//write(byte[] b,int off,int len):将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此缓冲的输出流。
outBuffer.write(bs, 0, len);
}
System.out.println("复制文件所需的时间:" + (System.currentTimeMillis() - begin)); // 平均时间约 200 多毫秒
inBuffer.close();
in.close();
outBuffer.close();
out.close();
}
@Test
public void test15() throws IOException {
// 不使用缓冲
FileInputStream in = new FileInputStream("E:\\视频资料\\大数据原理与应用\\1.1大数据时代.mp4");
FileOutputStream out = new FileOutputStream("1.1大数据时代.mp4");
int len = 0;
long begin = System.currentTimeMillis();
while ((len = in.read()) != -1) {
out.write(len);
}
System.out.println("复制文件所需时间:" + (System.currentTimeMillis() - begin)); // 平均时间约 160000 毫秒,约 2 分多钟
in.close();
out.close();
}
4、从控制台读入数据(很少用):
字节流相关的InputStreamReader的使用
JDK官方文档(可忽略): public class InputStreamReader extends ReaderInputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset
读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。 每次调用
InputStreamReader 中的一个 read()
方法都会导致从底层输入流读取一个或多个字节。要启用从字节到字符的有效转换,可以提前从底层流读取更多的字节,使其超过满足当前读取操作所需的字节。
为了达到最高效率,可要考虑在 BufferedReader 内包装 InputStreamReader。例如:
BufferedReader in= new BufferedReader(new
InputStreamReader(System.in));
public class IoTest {
public static void main(String[] args) throws IOException {
//test01();
//test02();
//test03();
}
/**
* 读取单个字符
* @throws IOException
*/
public static void test01() throws IOException {
//官方:InputStreamReader(InputStream in) 创建一个使用默认字符集的 InputStreamReader。
InputStreamReader inputStreamReader=new InputStreamReader(System.in);//System下的常量in是InputStream类型的
//官方:BufferedReader(Reader in) 创建一个使用默认大小输入缓冲区的缓冲字符输入流。
BufferedReader bufferedReader=new BufferedReader(inputStreamReader);//把读进来的字符流放入缓冲区
System.out.println("请输入一个字符:");
char c;
c=(char) bufferedReader.read();//读单个字符的read方法
System.out.println("你输入的字符为:"+c);
}
/**
*循环使用读单字符的read
* @throws IOException
*/
public static void test02() throws IOException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入一个字符,按 q 键结束");
char c;
do {
c = (char) bufferedReader.read();
System.out.println("你输入的字符为"+c);
} while (c != 'q');
}
/**
* 读取一行
* @throws IOException
*/
public static void test03() throws IOException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入一行字符");
//readLine();读取一个文本行。
String str = bufferedReader.readLine();
System.out.println("你输入的字符为" + str);
}
}
还可以用字符流和字节流的转换类进行两种流的转换:
/**
* 使用 字节流和字符流的转换类 进行编码设置
* @throws IOException
*/
@Test
public void test10() throws IOException {
FileOutputStream fileOutputStream = new FileOutputStream(new File("").getAbsolutePath()+"/io/test2.txt");
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, "GBK"); // 使用 GBK 编码文件
outputStreamWriter.write("Hello,world!\n欢迎来到 java 世界\n");
outputStreamWriter.append("另外一行内容");
outputStreamWriter.flush();
System.out.println("文件的编码为" + outputStreamWriter.getEncoding());
outputStreamWriter.close();
fileOutputStream.close();
}
@Test
public void test11() throws IOException {
FileInputStream fileInputStream = new FileInputStream(new File("").getAbsolutePath()+"/io/test2.txt");
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "GBK"); // 使用 GBK 解码文件
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str;
while ((str = bufferedReader.readLine()) != null) {
System.out.println(str);
}
bufferedReader.close();
inputStreamReader.close();
}
上一篇: 伪静态web.config配置步骤
下一篇: IO流