/**
* JAVA IO java 的输入与输出
* java使用输入与输出的两个方向来规定读和写的操作
* 其中输入是从外界到我们写的程序的方向是获取过程 是【读取】的操作
* 而输出则是发送到外界的方向 是【写出】的操作
*
* java将IO比喻为“流” 我们可以理解为是连接我们写的程序与外界设备之间的“管道”,类似现实
* 生活中的管道 只不过这个管子流的不是水 而是【字节】
*
* java.io.InputStream和OutputStream是所有字节输入流与输出流的超类 它们是抽象类
* InputStream定义了读取字节的相关方法 OutputStream定义了写出字节的相关方法
* 实际开发中我们可以创造不同的种类的输入与输出流来链接对应的设备进行读写操作
*
* 文件流
* java.io.FileInputStream和FileOutputStream 它们继承自InputStream
* OutputStream是实际用于读写文件的流
*/
public class FOSDemo {
public static void main(String[] args) throws IOException {
//向文件fos.dat中写入一个字节
/*
文件输出异常的构造方法
FileOutputStream(String path)
FileOutputStream(File file)
File file = new File("./fos.dat");
FileOutputStream fos = new FileOutputStream(file);
*/
FileOutputStream fos = new FileOutputStream("./fos.dat"); //文件所在的目录必须存在
/*
void write(int d)
写出一个字节,写出的内容是给定的int值对应的2进制的“低八位”
fos.write(2);
int型整形2的2进制
00000000 00000000 00000000 00000010
fos.dat的内容:
00000010
*/
//fos.write(-1);
fos.write(1);
fos.write(2);
System.out.println("写出完毕");
fos.close(); //关闭写出流
}
}
2./*
int read();
读取一个字节,并以int型返回,返回的int值对应的2进制的低八位为读取到的字节数据,
如果返回值为int的-1则表示读取到了流的末尾
fis.dat中:
00000001 00000010
读取到的:(前面3个字节补0)
00000000 00000000 00000000 00000001
00000000 00000000 00000000 00000010
*/
public class FISDemo {
public static void main(String[] args) throws IOException {
//将fos.dat文件中的数据读取回来
/*
int read();
读取一个字节,并以int型返回,返回的int值对应的2进制的低八位为读取到的字节数据,
如果返回值为int的-1则表示读取到了流的末尾
fis.dat中:
00000001 00000010
读取到的:(前面3个字节补0)
00000000 00000000 00000000 00000001
00000000 00000000 00000000 00000010
*/
FileInputStream fis = new FileInputStream("./fos.dat");
int d = fis.read();
System.out.println(d);//1
d = fis.read();
System.out.println(d);//2
d = fis.read();
System.out.println(d);//-1
fis.close();//关闭读取流
}
}
public class FISDemo {
public static void main(String[] args) throws IOException {
/*
fos.dat文件内容
00000001 00000011
*/
FileInputStream fis = new FileInputStream("fos.dat");
/*
int read()
读取一个字节,并一int型返回。返回的整数中读取的字节部分在该整数2进制的最后8位上
如果返回值为整数-1,则表示流读取到了末尾。对于读取文件而言就是EOF(end of file
文件末尾)
第一次调用read():
int d = fis.read();
fos.dat文件内容
00000001 00000011
^^^^^^^^
读取该字节
返回int值时,2进制样子:
00000000 00000000 00000000 00000001
^^^^^^^^
|-----补充24个0(3字节)-----| 读取的字节
返回的int值d就是上述内容
*/
int d = fis.read();
System.out.println(d);
/*
第二次调用read()
d = fis.read();
fos.dat文件内容
00000001 00000011
^^^^^^^^
读取该字节
返回int值时,2进制样子:
00000000 00000000 00000000 00000011
^^^^^^^^
|-----补充24个0(3字节)-----| 读取的字节
返回的int值d就是上述内容
*/
d = fis.read();
System.out.println(d);
/*
第三次调用read()
d = fis.read();
fos.dat文件内容
00000001 00000011
^^^^^^^^
文件末尾了
返回int值时,2进制样子:
11111111 11111111 11111111 11111111
^^^^^^^^
|-----补充32个1(4字节,来表示-1)-----|
返回的int值d就是上述内容
*/
d = fis.read();
System.out.println(d);
fis.close();
}
}
3.
public class Test {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("test.txt");
for(char i = 'a';i<='z';i++){
fos.write(i);
System.out.println(i);
}
System.out.println("写出完毕!");
fos.close();
}
}
public class test11 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("test.txt");
for (int i = 0; i < 26; i++) {
char b = (char)fis.read();
System.out.println(b);
}
}
}
4.
public class CopyDemo {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("fuyi.jpg");
FileOutputStream fos = new FileOutputStream("Image.jpg");
int d;
long start = System.currentTimeMillis();
while ((d = fis.read())!=-1){
fos.write(d);
}
long end = System.currentTimeMillis();
System.out.println("复制完毕"+(end-start)+"ms");
fis.close();
fos.close();
/*
File file = new File("fuyi.jpg");
for(int i = 1;i<=file.length();i++){
int b = fis.read();
fos.write(b);
}
System.out.println("复制完毕");
fis.close();
fos.close();
*/
}
}
public class CopyDemo {
public static void main(String[] args) throws IOException {
//创建文件输入流读取原文件
FileInputStream fis = new FileInputStream("image.jpg");
//创建文件输出流写入复制文件
FileOutputStream fos = new FileOutputStream("image_cp.jpg");
int d;//保存每次读取到的字节
/*
原文件数据:
11000011 10101010 00001111 11001100 00110011 ...
^^^^^^^^
d = fis.read();
d:00000000 00000000 00000000 10101010
fos.write(d);
复制文件的数据:
11000011 10101010
*/
long start = System.currentTimeMillis();//获取当前系统时间的毫秒值(UTC时间)
while((d = fis.read()) != -1) {
fos.write(d);
}
long end = System.currentTimeMillis();//获取当前系统时间的毫秒值(UTC时间)
System.out.println("复制完毕!耗时:"+(end-start)+"ms");
fis.close();
fos.close();
}
}
5./**
* 通过提高每次读写的数据量 减少实际读写的次数 可以提高读写效率
*
* 单子节的读写属于随机读写形式
* 一组字节的读写属于块读写形式
* 大多数的硬件块读写都比随机读写性能好 尤其机械硬盘上体现的最为明显
*
* InputStream和OutputStream上定义了块读写数据相关方法
*/
public class CopyDemo2 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("yingyu.pdf");
FileOutputStream fos = new FileOutputStream("Image.pdf");
/*
InputStream中提供了块读操作
int read(byte[] data)
*/
byte[] data = new byte[1024*10];//10kb
int len; //每次实际读取到的字节数
long start = System.currentTimeMillis();
while ((len = fis.read(data)) != -1){
// fos.write(data);
fos.write(data,0,len);//从数组data的0位置开始,连续读len长度个。
}
long end = System.currentTimeMillis();
System.out.println("复制完毕"+(end-start)+"ms");
fis.close();
fos.close();
}
}
### 块读写的文件复制操作
int read(byte[] data)
一次性从文件中读取给定的字节数组总长度的字节量,并存入到该数组中。
返回值为实际读取到的字节量。若返回值为-1则表示读取到了文件末尾。
块写操作
void write(byte[] data)
一次性将给定的字节数组所有字节写入到文件中
void write(byte[] data,int offset,int len)
一次性将给定的字节数组从下标offset处开始的连续len个字节写入文件
/**
* 通过提高每次读写的数据量,减少实际读写的次数,可以提高读写效率。
* 单字节读写是一种随机读写形式。而一组一组字节的读写是块读写形式。
*/
public class CopyDemo2 {
public static void main(String[] args) throws IOException {
//使用块读写形式完成文件复制
//创建文件输入流读取原文件
FileInputStream fis = new FileInputStream("wnwb.exe");
//创建文件输出流写复制文件
FileOutputStream fos = new FileOutputStream("wnwb_cp.exe");
/*
流提供了块读写的方法
int read(byte[] data)
一次性从文件中读取给定的字节数组总长度的字节量,并存入到该数组中。
返回值为实际读取到的字节量。若返回值为-1则表示读取到了文件末尾。
文件数据
11001100 11110000 10101010 00001111 00110011
^^^^^^^^ ^^^^^^^^ ^^^^^^^^
int d;
byte[] data = new byte[3];
[00000000 00000000 00000000]
第一次调用
d = fis.read(data);
[11001100 11110000 10101010]
d = 3 本次读取到了3个字节
文件数据
11001100 11110000 10101010 00001111 00110011
^^^^^^^^ ^^^^^^^^
第二次调用
d = fis.read(data);//仅读取了最后两个字节
[00001111 00110011 10101010]//前两个字节为本次读取的内容
^^^^^^^^ ^^^^^^^^
d = 2 本次读取到了2个字节
文件数据
11001100 11110000 10101010 00001111 00110011 文件末尾!
^^^^^^^^
第三次调用
d = fis.read(data);//一个字节都没有读取到
[00001111 00110011 10101010]数组没变化
d = -1 文件末尾
块写操作
void write(byte[] data)
一次性将给定的字节数组所有字节写入到文件中
void write(byte[] data,int offset,int len)
一次性将给定的字节数组从下标offset处开始的连续len个字节写入文件
*/
int len;//记录每次实际读取的字节量
/*
00000000 1byte 8位2进制称为1字节
1024byte 1kb
1024kb 1mb
1024mb 1gb
*/
byte[] data = new byte[1024*10];//10kb
long start = System.currentTimeMillis();
while((len = fis.read(data))!=-1){
fos.write(data,0,len);//读取多少就写多少
}
long end = System.currentTimeMillis();
System.out.println("复制完毕!耗时:"+(end-start)+"ms");
fis.close();
fos.close();
}
}
6.
//向文件中写入文本数据
public class WriteStringDemo {
public static void main(String[] args) throws IOException {
//ture是追加写,false相当于覆盖写,相当于什么都没写
//覆盖写:将原来文件中的内容抹除,重新写
//追加写:在原来文件中内容后面追加内容
FileOutputStream fos = new FileOutputStream("fos.txt",false);
String line = "super idol的笑容都没你的甜";
byte[] data = line.getBytes(StandardCharsets.UTF_8); //字符串转二进制
fos.write(data);
String line1 = ",滴滴青春蒸馏水";
data = line1.getBytes(StandardCharsets.UTF_8);
fos.write(data);
System.out.println("写出完毕");
fos.close();
}
}
public class WriteStringDemo {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("demo.txt");
String str = "super idol的笑容都没你的甜,";
/*
支持中文的常见字符集有:
GBK:国标编码。英文每个字符占1个字节,中文每个字符占2个字节
UTF-8:内部是unicode编码,在这个基础上不同了少部分2进制信息作为长度描述
英文每个字符占1字节
中文每个字符占3字节
String提供了将字符串转换为一组字节的方法
byte[] getBytes(String charsetName)
参数为字符集的名字,名字不缺分大小写,但是拼写错误会引发异常:
UnsupportedEncodingException
不支持 字符集 异常
*/
byte[] data = str.getBytes("UTF-8");
fos.write(data);
fos.write("八月正午的阳光,都没你耀眼。".getBytes("UTF-8"));
System.out.println("写出完毕!");
fos.close();
}
}
7.
public class NoteDemo {
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(System.in);
FileOutputStream fos = new FileOutputStream("./note.txt");
while(true){
String line = sc.nextLine();
if("exit".equals(line)){ //防止空指针异常,反过来写。空指针不能调用equals。
break;
}
byte[] data = line.getBytes(StandardCharsets.UTF_8);
fos.write(data);
}
System.out.println("完毕!");
fos.close();
/*
String i;
byte[] b;
while(!((i=scan.next()).equals("exit"))){
b = i.getBytes(StandardCharsets.UTF_8);
fos.write(b);
}
*/
}
}
8.
/**
* 从文件中读取文本数据
*/
public class ReadStringDemo {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("fos.txt");
byte[] data = new byte[1024];
int len = fis.read(data);//块读操作
System.out.println("实际读取到了"+len+"个字节");
/*
String提供了将字节数组转换为字符串的构造方法:
String(byte[]data,String charsetName)
将给定的字节数组中所有字节按照指定的字符集转换为字符串
String(byte[]data,int offset,int len,String charsetName)
将给定的字节数组从下标offset处开始的连续len个字节按照指定的字符集转换为字符串
*/
String line = new String(data,0,len,"UTF-8");
System.out.println(line);
System.out.println(line.length());
fis.close();
}
}
9./**
* java将流分为节点流与处理流两类
* 节点流:也称为低级流,是真实连接程序与另一端的"管道",负责实际读写数据的流。
* 读写一定是建立在节点流的基础上进行的。
* 节点流好比家里的"自来水管"。连接我们的家庭与自来水厂,负责搬运水。
* 处理流:也称为高级流,不能独立存在,必须连接在其他流上,目的是当数据经过当前流时
* 对其进行某种加工处理,简化我们对数据的同等操作。
* 高级流好比家里常见的对水做加工的设备,比如"净水器","热水器"。
* 有了它们我们就不必再自己对水进行加工了。
* 实际开发中我们经常会串联一组高级流最终连接到低级流上,在读写操作时以流水线式的加工
* 完成复杂IO操作。这个过程也称为"流的连接"。
*
* 缓冲流,是一对高级流,作用是加快读写效率。
* java.io.BufferedInputStream和java.io.BufferedOutputStream
*
*/
public class CopyDemo3 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("fuyi.jpg");
BufferedInputStream bis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream("Image.jpg");
BufferedOutputStream bos = new BufferedOutputStream(fos);
int d;
long start = System.currentTimeMillis();
while ((d = bis.read())!=-1){
bos.write(d);
}
long end = System.currentTimeMillis();
System.out.println("复制完毕"+(end-start)+"ms");
bis.close();//高级流自动关闭低级流
bos.close();//高级流自动关闭低级流
/*
File file = new File("fuyi.jpg");
for(int i = 1;i<=file.length();i++){
int b = fis.read();
fos.write(b);
}
System.out.println("复制完毕");
fis.close();
fos.close();
*/
}
}
10.
### 文件输出流-追加模式
重载的构造方法可以将文件输出流创建为追加模式
- FileOutputStream(String path,boolean append)
- FileOutputStream(File file,boolean append)
当第二个参数传入true时,文件流为追加模式,即:指定的文件若存在,则原有数据保留,新写入的数据会被顺序的追加到文件中
/**
* 文件流的追加写模式
*/
public class FileAppendDemo {
public static void main(String[] args) throws IOException {
/*
FileOutputStream默认创建方式为覆盖模式,即:如果连接的文件存在,
则会将该文件原有数据全部删除。然后将通过当前流写出的内容保存到文件中。
重载的构造方法允许我们再传入一个boolean型参数,如果这个值为true,则
文件流为追加模式,即:若连接文件时该文件存在,原有数据全部保留,通过当前
流写出的数据会顺序的追加到文件中。
*/
FileOutputStream fos = new FileOutputStream(
"demo.txt",true
);
fos.write("热爱105°的你,".getBytes("UTF-8"));
fos.write("滴滴清纯的蒸馏水。".getBytes("UTF-8"));
System.out.println("写出完毕!");
fos.close();
}
}
补充: