流的概念
数据的传输称为流,流的本质是数据传输。
流是一组有序的,有起点和终点的字节集合,是对计算机中数据传输的总称或者抽象。
流序列中的数据可以是没有进行加工的原始数据(二进制字节数据),也可以是经过编码的符合某种格式规定的数据,Java中提供了不同的流类对它们进行处理。
流有两个端点,起始位置 —> 目的地。
一端发送,另外一端接收。
输入流/输出流:都是从jvm角度来讲的。
把任何外界数据读到java中,这就是输入流。
把任何java中的数据写到外界,都是输出流。
输出流代表:System.out.print;
起点:jvm
终点:控制台
输入流代表:new Scanner(System.in);
起点:键盘->电脑操作系统
终点:jvm
------------------------------------------------------------------------------------------------------------------------------
流的分类
按照流传输方向不同:
输入流(InputStream)
输出流(OutputStream)
按照处理数据类型的不同:
字节流
字符流
按照流的基本功能不同:
节点流(基本流,传输最基本的字节或字符)
过滤流(对节点流的扩展,传对象,传double,传String等等)
------------------------------------------------------------------------------------------------------------------------------
字节流
FileInputStream读取文件
FileInputStream常用方法:
构造方法:
FileInputStream(String filename)
FileInputStream(File file)
常用方法:
close()
int read() (没有参数,返回值是byte值)
int read(byte[ ] b) (有参数,返回的是本次读取的长度)
int read(byte[ ] bs,int off,int len)
package demo;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class Input {
public static void main(String[] args) {
File file = new File("D:/abc/book.txt");
try {
//建立一条从文件到程序(jvm)的管道
FileInputStream in = new FileInputStream(file);
//声明一个空的比特数组,用于存放数据
byte[] bs = new byte[128];
//从文件中读取数据,填充数组,返回读取到的长度
//int len = in.read(bs);
//读取数据,放入数组中的指定位置
int len = in.read(bs,5,30);
System.out.println("读到长度:"+len);
String data = new String(bs);
System.out.println(data);
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果:
package demo;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class FileTest1 {
public static void main(String[] args) {
File file = new File("D:/abc/book.txt");
try {
FileInputStream in = new FileInputStream(file);
byte[] bs = new byte[2];
for(int i = 0;i < (file.length()/bs.length);i++)
{
in.read(bs);
String str = new String(bs);
System.out.println(str);
}
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果:
------------------------------------------------------------------------------------------------------------------------------
字节流
FileOutputStream写文件
FileOutputStream常用方法:
构造方法:
FileOutputStream(String path)
FileOutputStream(File file)
FileOutputStream(String path,boolean append)
FileOutputStream(File file,boolean append)
常用方法:
close()
void write(int v)
void write(byte[ ] bs)
void write(byte[ ] bs,int off,int len)
package demo;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class OutputTest {
public static void main(String[] args) {
File file = new File("D:/abc/输出流测试.txt");
if(!file.exists()){
try {
file.createNewFile();
} catch (Exception e) {
e.printStackTrace();
}
}
try {
//java连接文件,从java到目标文件的管道
FileOutputStream out = new FileOutputStream(file);
String str = "无敌是多么寂寞~";
out.write(str.getBytes());
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果:
------------------------------------------------------------------------------------------------------------------------------
用流复制文件-通用全能方案
package demo;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
public class FileCopy {
public static void main(String[] args) {
/**
* 把src赋复制到local
*/
File src = new File("D:/MyWeb/images/表情包.jpg");
File local = new File("D:/abc/"+src.getName());
try {
//建立连接管道
FileInputStream in = new FileInputStream(src);
FileOutputStream out = new FileOutputStream(local);
byte[] bs = new byte[256];
/*
while(true){
int len = in.read(bs);
if(len != -1){
out.write(bs,0,len);
}
else {
//结束循环
break;
}
}
*/
for(int len=0;(len=in.read(bs)) != -1;){
out.write(bs,0,len);
}
//释放资源
in.close();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
------------------------------------------------------------------------------------------------------------------------------
断点续传-制造断点文件
package demo;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
public class BreakPoint {
public static void main(String[] args) {
File src = new File("D:/MyWeb/images/表情包.jpg");
File local = new File("D:/abc/"+src.getName());
try {
//建立连接管道
FileInputStream in = new FileInputStream(src);
FileOutputStream out = new FileOutputStream(local);
byte[] bs = new byte[256];
long over = 0;
for(int len=0;(len=in.read(bs)) != -1;){
out.write(bs,0,len);
//文件传一半,断掉
over += len;
if(over > src.length()/2) {
System.out.println("出现断点");
break;
}
}
//释放资源
in.close();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果:
------------------------------------------------------------------------------------------------------------------------------
断点续传-实现续传功能
断点续传核心技术点:输出流设置追加,输入流设置跳过
package demo;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
public class BreakPointResume {
public static void main(String[] args) {
/**
* 把src赋复制到local
* 支持断点续传(核心技术点:输出流设置追加,输入流设置跳过)
*/
File src = new File("D:/MyWeb/images/表情包.jpg");
File local = new File("D:/abc/"+src.getName());
//文件开始位置
long start = 0;
if(src.length() == local.length()) {
System.out.println("文件已经存在,无需复制");
}
else if(src.length()> local.length()) {
System.out.println("断点文件,需要续传");
start = local.length();
}
else if(local.length() == 0) {
System.out.println("文件不存在,开始复制");
}
try {
//建立连接管道
FileInputStream in = new FileInputStream(src);
FileOutputStream out = new FileOutputStream(local,true);
byte[] bs = new byte[256];
//设置输入流起始位置
in.skip(start);
for(int len=0;(len=in.read(bs)) != -1;){
out.write(bs,0,len);
}
//释放资源
in.close();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
------------------------------------------------------------------------------------------------------------------------------
编写文件工具类
如果我们想要复制多个文件的话,就需要编写文件工具类。
package demo;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class MyFileUtil {
public static void copy(String src,String target) throws FileNotFoundException {
File f1 = new File(src);
File f2 = new File(target);
copy(f1,f2);
}
public static void copy(File src,File target) throws FileNotFoundException {
InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(target);
copy(in,out);
}
public static void copy(InputStream in,OutputStream out) {
try {
byte[] bs = new byte[2048];
for(int len=0;(len=in.read(bs)) != -1;) {
out.write(bs,0,len);
}
out.close();
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
package demo;
import java.io.File;
import java.io.FileNotFoundException;
public class MyFileUtilTest {
public static void main(String[] args) {
File file1 = new File("D:/abc/book.txt");
File file2 = new File("D:/abc/MyUtilTest.txt");
try {
MyFileUtil.copy("D:/abc/book.txt","D:/abc/MyUtilTest.txt");
MyFileUtil.copy(file1,file2);
} catch (FileNotFoundException e) {
System.out.println("复制文件的时候发生异常,此处可以编写各种代码");
e.printStackTrace();
}
}
}
运行结果:
------------------------------------------------------------------------------------------------------------------------------
java测试字符集
常见的编码规范(字符集):
ASCII
ISO-8859-1
GBK
UTF-8
乱码问题
package demo;
import java.io.UnsupportedEncodingException;
public class Test2 {
public static void main(String[] args) throws UnsupportedEncodingException {
String str = "小奶狗";
byte[] bs = str.getBytes("GBK");
byte[] bs2= str.getBytes("UTF-8");
for(byte b : bs) {
System.out.println(b);
}
System.out.println("—————" + bs.length);
System.out.println("=====" + bs2.length);
String str2 = new String(bs2, "UTF-8");
System.out.println(str2);
byte[] little = new byte[] {-48,-95};
String xiao = new String(little,"GBK");
System.out.println(xiao);
}
}
运行结果:
------------------------------------------------------------------------------------------------------------------------------
字符流
字符流用于处理文字传输,涉及到字符集的内容。
字节流用于处理文件传输。
– 底层也是比特流,只是经过了字符编码的处理。
– 可以认为 R/W 就是字符转换器。
FileReader常用方法:
FileReader(String fileName)
close()
int read(char[ ] ch)
FileWriter常用方法:
FileWriter(String fileName)
close()
void write(String value)
FileReader和FileWriter只用于连接文件,通用性不强,因为大多数时候我们都是通过网络传输。其次,它们不能设置字符集。
package demo;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class Test1 {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("D:/abc/book.txt");
FileWriter fw = new FileWriter("D:/abc/new.txt");
String value = "纵情山河万里!";
char[] val = value.toCharArray();
fw.write(val);
fw.flush();
char[] ch = new char[256];
int n = fr.read(ch);
String str = new String(ch,0,n);
System.out.println(n);
System.out.println(str);
fr.close();
fw.close();
}
}
运行结果:
InputStreamReader和OutputStreamWriter特点:
1.可以把一个字节流转换成一个字符流。
2.在转换时可以指定字符集。
InputStreamReader常用方法:
InputStreamReader(InputStream in)
InputStreamReader(InputStream in,String charSet)
int read(char[] cbuf)
OutputStreamWriter常用方法:
OutputStreamWriter(OutputStream out)
OutputStreamWriter(OutputStream out,String charSet)
void write(String value)
package demo;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
public class Test3 {
public static void main(String[] args) {
try {
File file = new File("D:/abc/book.txt");
InputStream in = new FileInputStream(file);
InputStreamReader isr = new InputStreamReader(in,"UTF-8");
char[] val = new char[16];
int len = isr.read(val);
System.out.println("长度:"+len);
System.out.println(val);
isr.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果:
package demo;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
public class Test4 {
public static void main(String[] args) {
File file = new File("D:/abc/book2.txt");
String str = "流光容易把人抛,红了樱桃,绿了芭蕉";
try {
OutputStream out = new FileOutputStream(file);//会创建新文件
OutputStreamWriter osw = new OutputStreamWriter(out, "UTF-8");
osw.write(str);;
osw.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果:
------------------------------------------------------------------------------------------------------------------------------
过滤流
过滤流的开发步骤:
1.创建节点流。
2.基于节点流创建过滤流。
3.读/写数据。
4.关闭外层流。
DataOutputStream过滤流演示:
package demo;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class Test5 {
public static void main(String[] args) {
File file = new File("D:/abc/book3.txt");
try {
//因为只有最基本的读写功能,所以叫节点流
//因为是用来处理字节的流,所以叫字节流
OutputStream out = new FileOutputStream(file);
//基于节点流创建过滤流,是个高级流
DataOutputStream dos = new DataOutputStream(out);
//调用过滤流中的高级方法书写数据
dos.writeDouble(3.1415926);
dos.writeInt(99);
dos.writeChars("HelloWorld!");
//关闭最外层流即可
dos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果(能够读出来即可):
DataInputStream过滤流演示
package demo;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
public class Test6 {
public static void main(String[] args) {
File file = new File("D:/abc/book3.txt");
try {
InputStream in = new FileInputStream(file);
DataInputStream dis = new DataInputStream(in);
double num1 = dis.readDouble();
int num2 = dis.readInt();
String str = dis.readUTF();
System.out.println(num1);
System.out.println(num2);
System.out.println(str);
dis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果:
------------------------------------------------------------------------------------------------------------------------------
BufferedStream:带有缓冲区,用法同上。
BufferedInputStream
BufferedOutputStream
------------------------------------------------------------------------------------------------------------------------------
对象流与对象序列化
ObjectInputStream常用方法:
readObject()
ObjectOutputStream常用方法:
writeObject()
Serializable接口不需要实现任何方法,实现这个接口之后这个类就可以被序列化,可以通过流进行传输。
transient代表某项属性不参与序列化活动。
transient关键字需要注意:如果一个对象的属性又是一个对象,则要求这个属性对象也实现了Serializable接口。
package demo;
import java.io.Serializable;
public class Player implements Serializable {
private String name;
transient private String level;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLevel() {
return level;
}
public void setLevel(String level) {
this.level = level;
}
public Player(String name,String level)
{
this.name = name;
this.level = level;
}
}
package demo;
import java.io.File;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
public class Test7 {
public static void main(String[] args) {
Player girl = new Player("小奶狗","最强王者");
Player boy = new Player("小狼狗","倔强青铜");
File file = new File("D:/abc/introduce.txt");
try {
OutputStream out = new FileOutputStream(file);
ObjectOutputStream oos = new ObjectOutputStream(out);
oos.writeObject(girl);
oos.writeObject(boy);
oos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
package demo;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;
public class Test8 {
public static void main(String[] args) {
File file = new File("D:/abc/introduce.txt");
try {
InputStream in = new FileInputStream(file);
ObjectInputStream ois = new ObjectInputStream(in);
Player p1 = (Player) ois.readObject();
Player p2 = (Player) ois.readObject();
System.out.println(p1.getName()+":"+p1.getLevel());
System.out.println(p2.getName()+":"+p2.getLevel());
ois.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果:
------------------------------------------------------------------------------------------------------------------------------
总结:
字符过滤流:
readLine() 读取一行。
writeLine() 写一行。
各种过滤流都是基本流的扩展。
共有方法:
write
read
独有方法:
DataStream:基本数据类型的直接读写。
BufferedStream:带有缓冲区,看起来速度好快。
ObjectStream:对象读写。
对象序列化:实现Serializable接口。
来源:https://blog.csdn.net/weixin_44585214/article/details/100566850