IO流的原理及流的分类
IO技术用于处理设备之间的数据传输;输入input: 读取外部数据(磁盘,光盘等存储设备)到程序(内存)中;输出output: 将程序(内存)数据输出到外部数据(磁盘,光盘等存储设备);
流的分类:
- 按操作数据单位不同分为: 字节流, 字符流
字节流: 读入或写出的基本单位是byte字节, 通常用于非文本文件的读入和写出, 单纯的文件复制, 文本文件也可使用字节流操作;
字符流: 读入或写出的基本单位是char字符, 通常用于文本文件的读入和写出, 不可以用于非文本文件; - 按照数据流的流向不同分为: 输入流, 输出流
输入流: 读取外部数据到程序中
输出流: 从程序中向外部硬件写出数据,序列化 - 按照流的角色不同分为: 节点流, 处理流
节点流: 直接作用域文件上的流: 通过File类实例化;
处理流: 包装已经存在的流: 通过已存在的流实例化;
IO流体系
分类 | 字节输入流 | 字节输出流 | 字符输入流 | 字符输出流 |
---|---|---|---|---|
抽象基类 | InputStream | OutputStream | Reader | Writer |
字节流(文件流) | FileInputStream | FileOutputStream | FileReader | FileWriter |
缓冲流 | BufferedInputStream | BufferedOutputStream | BufferedReader | BufferedWriter |
转换流 | InputStreamReader | OutputStreamWriter | ||
对象流 | ObjectInputStream | ObjectOutputStream |
流操作步骤
- File类的实例化
- 流的实例化
- 读入或输出的操作
- 流资源的关闭: 先关闭外层流, 再关闭内层流
使用字符流复制文本文件
public void copyByReaderWriter(String sourcePath, String dscPath) {
FileReader fr = null;
FileWriter fw = null;
try {
// 实例化 File 和实例化 字符流 这里的file 只能是文本类的文件
fr = new FileReader(new File(sourcePath));
fw = new FileWriter(new File(dscPath));
// 字符数组存储每次从输入流读到的数据 每次最多读取1024个长度的字符
char[] cubf = new char[1024];
int len = 0; // 记录每次读到的字符长度
while ((len = fr.read(cubf)) != -1) {
fw.write(cubf, 0, len); // 使用输出流将数据输出
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭流
if (fr != null) {
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fw != null) {
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
使用字节流复制文件
public void copyByInputOutStream(String sourcePath, String dscPath) {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
// 实例化 File 和实例化 字节流 这里的file 可以是文本类,也可以非文本类文件, 只不过复制文本类文件时, 不能在读取时将读取到的数据显示的打印出来, 因为字节读取可能会将文本中字符截断, 从而造成乱码
fis = new FileInputStream (new File(sourcePath));
fos = new FileOutputStream (new File(dscPath));
// 字节数组存储每次从输入流读到的数据 每次最多读取1024个长度的字节
byte[] buffer = new byte[1024];
int len = 0; // 记录每次读到的字节长度
while ((len = fis.read(buffer)) != -1) {
fos.write(buffer, 0, len); // 使用输出流将数据输出
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭流
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
使用字符缓冲流复制文本文件
public static void copyByBufferReaderWriter(String sourcePath, String dscPath) {
BufferedReader br = null;
BufferedWriter bw = null;
try {
br = new BufferedReader(new FileReader(new File(sourcePath)));
bw = new BufferedWriter(new FileWriter(new File(dscPath)));
//方式一 字符读取
//char[] cubf = new char[2];
//int len;
//while ((len = br.read(cubf)) != -1) {
// bw.write(cubf,0,len);
//}
// 方式二 按行读取
String s = null;
while ((s = br.readLine()) != null) {
bw.write(s);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bw != null) {
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
使用字节缓冲流复制文件
public static void copyByBufferedStream(String sourcePath, String dscPath){
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
bis = new BufferedInputStream(new FileInputStream(new File(sourcePath)));
bos = new BufferedOutputStream(new FileOutputStream(new File(dscPath)));
byte[] buffer = new byte[1024];
int len;
while ((len = bis.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
使用转换流转换文本编码
public static void transferByStreamReaderWriter(String sourcePath, String sourceCharset, String dscPath, String dscCharset){
InputStreamReader isr = null;
OutputStreamWriter osw = null;
try {
isr = new InputStreamReader(new FileInputStream(new File(sourcePath)),sourceCharset);
osw = new OutputStreamWriter(new FileOutputStream(new File(dscPath)), dscCharset);
char[] cbuf = new char[1024];
int len ;
while ((len = isr.read(cbuf)) != -1) {
osw.write(cbuf, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (osw != null) {
try {
osw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (isr != null) {
try {
isr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
其他流的说明
标准输入输出流:
System.in
: 默认识别键盘输入的标准输入流
System.out
: 默认输出至控制台的标准打印流;
public static void standardStream(){
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(System.in));
String data;
while ((data = br.readLine()) != null) {
if ("e".equalsIgnoreCase(data)||"exit".equalsIgnoreCase(data)) {
break;
}
System.out.println(data);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
打印流: PrintStream
和PrintWriter
处理流的一种, 搭配System.out
标准输出流使用, 替换System.out
中的标准输出流
public static void printStreamWriter(){
PrintStream ps = null;
try {
FileOutputStream fos = new FileOutputStream("data.txt");
ps = new PrintStream(fos, true);
// 默认是控制台输出的打印流, 改为向文件输出的打印流
System.setOut(ps);
for (int i = 20001; i<=20300; i++) {
System.out.print((char)i);
if (i%50 == 0) {
System.out.println();
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (ps != null) ps.close();
}
}
数据流: DataInputStream
和DataOutputStream
,这两个流可以序列化或反序列化JAVA的基本数据类型
对象流与序列化
对象序列化机制: 允许吧内存中的Java对象转换成平台无关的二进制流, 从而允许吧这种二进制流持久的保存在磁盘上, 或通过网络将这种二进制流传输到另一个网络节点. 当其他程序获取了这种二进制流, 就可以恢复为原来的Java对象;
Java对象可序列化需要满足的条件:
- 实现
Serializable
接口或Externalizable
- 提供一个全局常量:
serialVersionUID
- 对象的所有属性也必须是可序列化的
ObjectInputStream
和ObjectOutputStream
用于存储和读取基本数据类型或对象的处理流. 可以序列化或反序列化Java对象;
注: 被static
或transient
修饰的成员变量不能被ObjectOutputStream
序列化
// 序列化
public static void objectOutputStreamTest(){
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(new FileOutputStream("data.dat"));
oos.writeObject(new User("admin","123456"));
oos.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (oos != null) {
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
// 反序列化
public static void objectInputStreamTest(){
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream("data.dat"));
User user = (User) ois.readObject();
System.out.println(user);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/** 1.实现Serializable 接口
* 2. 提供常量serialVersionUID
* 3. 所有成员变量都可序列化
**/
class User implements Serializable {
public static final long serialVersionUID = 235684654516L;
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public User() {
}
public User(String username, String password) {
this.username = username;
this.password = password;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
RandomAccessFile 随机存取文件流
直接继承java.lang.Object, 实现了DataInput和DataOutput接口
既可以作为一个输入流,也可以作为一个输出流
作为输出流的时候, 写出到的文件如果不存在, 则在执行过程中自动创建.如果写出到的文件已存在,也会对源文件内容进行覆盖,默认情况下,从头覆盖;
可以通过相关的操作,实现插入数据的效果, 使用seek(int pos)移动读取的指针;
NIO.2
Path, Paths, Files;
TCP网络编程InetAddress/Socket/ServerSocket
客户端服务端文字传输对话
@Test
public void client() {
Socket socket = null;
OutputStream outputStream = null;
try {
// 实例化一个IP地址
InetAddress address = InetAddress.getByName("127.0.0.1");
// 实例化Socket
socket = new Socket(address, 8989);
// 获取输出流
outputStream = socket.getOutputStream();
// 写出数据
outputStream.write("我是客户端".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭流, 资源
if (outputStream != null)
{
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Test
public void server(){
ServerSocket ss = null;
Socket accept = null;
InputStream is = null;
ByteArrayOutputStream baos = null;
try {
ss = new ServerSocket(8989);
accept = ss.accept();
// 获取客户端Socket
is = accept.getInputStream();
byte[] buffer = new byte[5];
baos = new ByteArrayOutputStream();
int len;
while ((len = is.read(buffer)) != -1) {
baos.write(buffer,0,len);
}
System.out.println(baos.toString());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (baos != null) {
try {
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (accept != null) {
try {
accept.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (ss != null) {
try {
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
客户端服务端文件传输
@Test
public void client1() {
Socket s = null;
OutputStream os = null;
FileInputStream fis = null;
InputStream is = null;
ByteArrayOutputStream baos = null;
try {
InetAddress ia = InetAddress.getByName("127.0.0.1");
s = new Socket(ia, 8989);
os = s.getOutputStream();
fis = new FileInputStream("月球.jpg");
byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer)) != -1) {
os.write(buffer,0,len);
}
// 关闭Socket输出流 通知服务端文件传输完毕
s.shutdownOutput();
is = s.getInputStream();
baos = new ByteArrayOutputStream();
while ((len = is.read(buffer)) != -1) {
baos.write(buffer,0,len);
}
System.out.println(baos.toString());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (baos != null) {
try {
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (s != null) {
try {
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Test
public void server1(){
ServerSocket ss = null;
Socket accept = null;
InputStream is = null;
FileOutputStream fos = null;
OutputStream os = null;
try {
ss = new ServerSocket(8989);
accept = ss.accept();
is = accept.getInputStream();
fos = new FileOutputStream("月球copy.jpg");
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
fos.write(buffer,0,len);
}
os = accept.getOutputStream();
os.write("已接受文件".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (accept != null) {
try {
accept.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (ss != null) {
try {
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
UDP网络编程 DatagramSocket/DatagramPacket
@Test
public void sender(){
DatagramSocket ds = null;
try {
ds = new DatagramSocket();
byte[] data = "我是UDP".getBytes();
DatagramPacket dp = new DatagramPacket(data,0,data.length, InetAddress.getLocalHost(), 8989);
ds.send(dp);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ds != null)
ds.close();
}
}
@Test
public void receiver(){
DatagramSocket ds = null;
try {
ds = new DatagramSocket(8989);
byte[] data = new byte[1024];
DatagramPacket dp = new DatagramPacket(data,0,data.length);
ds.receive(dp);
System.out.println(new String(dp.getData(),0,dp.getLength()));
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ds != null)
ds.close();
}
}
URL网络编程
@Test
public void urlTest() {
InputStream is = null;
FileOutputStream fos = null;
try {
URL url = new URL("https://img12.360buyimg.com/n1/jfs/t1/165987/32/13853/446979/6058756bE2d8a210d/cfd6cd202564a589.jpg");
URLConnection urlConnection = url.openConnection();
urlConnection.connect();
is = urlConnection.getInputStream();
fos = new FileOutputStream("xiazai.jpg");
byte[] b = new byte[1024];
int len;
while ((len=is.read(b)) != -1) {
fos.write(b,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}