1:IO流的原理
- IO是Input/Output的缩写,用于处理设备之间的数据传输,如读写文件、网络通讯
- Java程序中,对于数据的输入/输出操作以“流”的方式进行
- java.io包下提供了各种流的接口和类,通过标准的方法输入或输出数据
2:流的分类
2.1:节点流和处理流的区别
处理流需要包装在节点流上
2.2:IO的体系
2.3:InputStream & Reader 的介绍
2.3.1:InputStream的方法
2.3.2:Reader的方法
2.4:OutputStream & Writer的介绍
2.4.1:OutputStream的常用方法
2.4.2:Writer的常用方法
2.5:举例说明
1: File file = new File("hello.txt");// F:\javaSenior\hello.txt 相较于当前工程,不是想当于module下面 System.out.println(file.getAbsolutePath()); File file1 = new File("day09\\hello.txt");//F:\javaSenior\day09\hello.txt System.out.println(file1.getAbsolutePath());在IDEA中,在main()方法里面创建的文件的路径是相对于工程下面的,不是相对于module,在Test测试方法里面是相对于module
2:将day09下的hello.txt文件内容读入程序中,并输出到控制台 hello.txt里面写的是abc123中国人
说明点: 1. read()的理解:返回读入的一个字符。如果达到文件末尾,返回-1
2. 异常的处理:为了保证流资源一定可以执行关闭操作。需要使用try-catch-finally处理
3. 读入的文件一定要存在,否则就会报FileNotFoundException。
//1:实例化File类的对象,指明要操作的文件 File file=new File( "hello.txt"); //相对于当前module下的 //2:提供具体的流 FileReader fr=new FileReader(file); //3:数据的读入 read():返回读入的一个字符,如果达到文件的末尾,返回- 1 //方式一: int data=fr.read(); while( data!=- 1) { System. out.println((char) data); data=fr.read(); } //方式二: int data; while(( data = fr.read()) != - 1){ System. out.print((char) data); }通过read()方法
//1:实例化File类的对象,指明要操作的文件 File file= new File( "hello.txt"); //相对于当前module下的 //2:提供具体的流 FileReader fr= new FileReader(file); //3.读入的操作 //read(char[] cbuf):返回每次读入cbuf数组中的字符的个数。如果达到文件末尾,返回-1 char[] cbuf = new char[ 6]; int len; while((len = fr.read(cbuf)) != -1){ //方式一: //错误的写法 for( int i = 0;i < cbuf.length;i++){ System. out.print(cbuf[i]); //txt文件是abc123中国人,数组的长度是5,每次要读入五个字符,第一次读出abc123,第二次读的时候用中国人去覆盖上一次的abc,123仍然还在,所以第二次读出的是中国人123,结果输出的是abc123中国人123 } //正确的写法 // for(int i = 0;i < len;i++){ // System.out.print(cbuf[i]);//每次读出字符实际的长度 // } //方式二: //错误的写法,对应着方式一的错误的写法 // String str = new String(cbuf); // System.out.print(str); //正确的写法 // String str = new String(cbuf,0,len); // System.out.print(str);总结:read(char[])方法在读取数据的时候,用下次去取出的字符去替代上一次所读出的字符(从下标0开始),所以读出的时候我们应该去取读出的实际长度。
3:从内存中写出数据到硬盘的文件里。输出操作
1. 输出操作,对应的File可以不存在的。并不会报异常 2. File对应的硬盘中的文件如果不存在,在输出的过程中,会自动创建此文件。 File对应的硬盘中的文件如果存在: 如果流使用的构造器是:FileWriter(file,false) / FileWriter(file):对原有文件的覆盖 如果流使用的构造器是:FileWriter(file,true):不会对原有文件覆盖,而是在原有文件基础上追加内容 */ @Test public void testFileWriter() { FileWriter fw = null; try { //1.提供File类的对象,指明写出到的文件 File file = new File("hello4.txt"); //2.提供FileWriter的对象,用于数据的写出 fw = new FileWriter(file,false); //3.写出的操作 fw.write("I have a dream!\n"); fw.write("you need to have a dream!"); } catch (IOException e) { e.printStackTrace(); } finally { //4.流资源的关闭 if(fw != null){ try { fw.close(); } catch (IOException e) { e.printStackTrace(); } } }4:将一个文件复制到另外一个文件
@Test public void testFileReaderFileWriter() { FileReader fr = null; FileWriter fw = null; try { //1.创建File类的对象,指明读入和写出的文件 File srcFile = new File( "hello.txt"); File destFile = new File( "hello2.txt"); //不能使用字符流来处理图片等字节数据 // File srcFile = new File("爱情与友情.jpg"); // File destFile = new File("爱情与友情1.jpg"); //2.创建输入流和输出流的对象 fr = new FileReader(srcFile); fw = new FileWriter(destFile); //3.数据的读入和写出操作 char[] cbuf = new char[ 5]; int len; //记录每次读入到cbuf数组中的字符的个数 while((len = fr.read(cbuf)) != - 1){ //每次写出len个字符 fw.write(cbuf, 0,len); } } catch (IOException e) { e.printStackTrace(); } finally
3:FileInputStream/FileInputStream说明
3.1:文件的输出
-
FileInputStream fis =
null;
-
try {
-
//1. 造文件
-
File file =
new File(
"hello.txt");
-
-
//2.造流
-
fis =
new FileInputStream(file);
-
int size = fis.available();
//这个方法可以预估字节流文件里面预估的流,一次读完
-
//3.读数据
-
byte[] buffer =
new
byte[size];
-
int len;
//记录每次读取的字节的个数
-
while((len = fis.read(buffer)) !=
-1){
-
-
String str =
new String(buffer,
0,size);
-
System.
out.println(str);
-
System.
out.println(
"************");
//总共只执行了一次
-
}
-
}
catch (IOException e) {
-
e.printStackTrace();
-
}
finally {
-
if(fis !=
null){
-
//4.关闭资源
-
try {
-
fis.close();
-
}
catch (IOException e) {
-
e.printStackTrace();
-
}
-
-
}
-
}
-
-
}
使用字节流FileInputStream处理文本文件,可能出现乱码。//1:造文件
File file = new File("hello.txt"); //2.造流 FileInputStream fis = new FileInputStream(file); //3.读数据 byte[] buffer = new byte[2]; int len;//记录每次读取的字节的个数 while((len = fis.read(buffer)) != -1){ String str = new String(buffer,0,size); System.out.println(str);}
假设:"hello.txt"里面有“a中国”三个字符,由于buffer数组每次读两个字节流,那么第一个字节流给a,另外一个字节流给“中”字,由于UTF-8一个汉字三个字节流,那么它另外两个字节流需要占用下一次读取的,会造成乱码,
解决方法:用字节流、或者给数组开辟的空间足够大,一次可以读取所有的字符
3.2:实现对图片的复制
-
/*
-
实现对图片的复制操作
-
*/
-
@Test
-
public void testFileInputOutputStream() {
-
FileInputStream fis =
null;
-
FileOutputStream fos =
null;
-
try {
-
//
-
File srcFile =
new File(
"爱情与友情.jpg");
-
File destFile =
new File(
"爱情与友情2.jpg");
-
-
//
-
fis =
new FileInputStream(srcFile);
-
fos =
new FileOutputStream(destFile);
-
-
//复制的过程
-
byte[] buffer =
new
byte[
5];
-
int len;
-
while((len = fis.read(buffer)) != -
1){
-
fos.write(buffer,
0,len);
-
}
-
-
}
catch (IOException e) {
-
e.printStackTrace();
-
}
finally {
-
if(fos !=
null){
-
//
-
try {
-
fos.close();
-
}
catch (IOException e) {
-
e.printStackTrace();
-
}
-
}
-
if(fis !=
null){
-
try {
-
fis.close();
-
}
catch (IOException e) {
-
e.printStackTrace();
-
}
-
-
}
-
}
-
-
}
4:节点流(或文件流):注意点
5:缓冲流
5.1:图片复制的案例
-
@Test
-
public void BufferedStreamTest() throws FileNotFoundException {
-
BufferedInputStream bis =
null;
-
BufferedOutputStream bos =
null;
-
-
try {
-
//1.造文件
-
File srcFile =
new File(
"爱情与友情.jpg");
-
File destFile =
new File(
"爱情与友情3.jpg");
-
//2.造流
-
//2.1 造节点流
-
FileInputStream fis =
new FileInputStream((srcFile));
-
FileOutputStream fos =
new FileOutputStream(destFile);
-
//2.2 造缓冲流
-
bis =
new BufferedInputStream(fis);
-
bos =
new BufferedOutputStream(fos);
-
-
//3.复制的细节:读取、写入
-
byte[] buffer =
new
byte[
10];
-
int len;
-
while((len = bis.read(buffer)) != -
1){
-
bos.write(buffer,
0,len);
-
-
// bos.flush();//刷新缓冲区
-
-
}
-
}
catch (IOException e) {
-
e.printStackTrace();
-
}
finally {
-
//4.资源关闭
-
//要求:先关闭外层的流,再关闭内层的流
-
if(bos !=
null){
-
try {
-
bos.close();
-
}
catch (IOException e) {
-
e.printStackTrace();
-
}
-
-
}
-
if(bis !=
null){
-
try {
-
bis.close();
-
}
catch (IOException e) {
-
e.printStackTrace();
-
}
-
-
}
-
//说明:关闭外层流的同时,内层流也会自动的进行关闭。关于内层流的关闭,我们可以省略.
-
// fos.close();
-
// fis.close();
-
}
5.2:文件复制的案例
-
@Test
-
public
void testBufferedReaderBufferedWriter(){
-
BufferedReader br =
null;
-
BufferedWriter bw =
null;
-
try {
-
//创建文件和相应的流
-
br =
new BufferedReader(
new FileReader(
new File(
"dbcp.txt")));
-
bw =
new BufferedWriter(
new FileWriter(
new File(
"dbcp1.txt")));
-
-
//读写操作
-
//方式一:使用char[]数组
-
// char[] cbuf = new char[1024];
-
// int len;
-
// while((len = br.read(cbuf)) != -1){
-
// bw.write(cbuf,0,len);
-
// // bw.flush();
-
// }
-
-
//方式二:使用String
-
String data;
-
while((data = br.readLine()) !=
null){
-
//方法一:
-
// bw.write(data + "\n");//data中不包含换行符
-
//方法二:
-
-
bw.write(data);
//data中不包含换行符
-
bw.newLine();
//提供换行的操作
-
-
}
-
-
-
}
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();
-
}
-
-
}
-
}
BufferedReader提供了readLine()方法来读取一行行的字符串BufferWriter提供了newLine()方法提供换行的操作
5.3:缓冲流的课后习题
5.3.1:图片的加密
-
//图片的加密
-
@Test
-
public void test1() {
-
-
FileInputStream fis =
null;
-
FileOutputStream fos =
null;
-
try {
-
fis =
new FileInputStream(
"爱情与友情.jpg");
-
fos =
new FileOutputStream(
"爱情与友情secret.jpg");
-
-
byte[] buffer =
new
byte[
20];
-
int len;
-
while ((len = fis.read(buffer)) != -
1) {
-
//字节数组进行修改
-
//错误的
-
// for(byte b : buffer){
-
// b = (byte) (b ^ 5);
-
// }
-
//正确的
-
for (
int i =
0; i < len; i++) {
-
buffer[i] = (
byte) (buffer[i] ^
5);
-
}
-
-
-
fos.write(buffer,
0, len);
-
}
-
}
catch (IOException e) {
-
e.printStackTrace();
-
}
finally {
-
if (fos !=
null) {
-
try {
-
fos.close();
-
}
catch (IOException e) {
-
e.printStackTrace();
-
}
-
-
}
-
if (fis !=
null) {
-
try {
-
fis.close();
-
}
catch (IOException e) {
-
e.printStackTrace();
-
}
-
-
}
-
}
-
-
-
}
-
-
-
//图片的解密
-
@Test
-
public void test2() {
-
-
FileInputStream fis =
null;
-
FileOutputStream fos =
null;
-
try {
-
fis =
new FileInputStream(
"爱情与友情secret.jpg");
-
fos =
new FileOutputStream(
"爱情与友情4.jpg");
-
-
byte[] buffer =
new
byte[
20];
-
int len;
-
while ((len = fis.read(buffer)) != -
1) {
-
//字节数组进行修改
-
//错误的
-
// for(byte b : buffer){
-
// b = (byte) (b ^ 5);
-
// }
-
//正确的
-
for (
int i =
0; i < len; i++) {
-
buffer[i] = (
byte) (buffer[i] ^
5);
-
}
-
-
fos.write(buffer,
0, len);
-
}
-
}
catch (IOException e) {
-
e.printStackTrace();
-
}
finally {
-
if (fos !=
null) {
-
try {
-
fos.close();
-
}
catch (IOException e) {
-
e.printStackTrace();
-
}
-
-
}
-
if (fis !=
null) {
-
try {
-
fis.close();
-
}
catch (IOException e) {
-
e.printStackTrace();
-
}
-
-
}
-
}
-
两次与的操作数据不变
5.3.2:获取文本上每个字符出现的次数
-
public
class
WordCount {
-
/*
-
说明:如果使用单元测试,文件相对路径为当前module
-
如果使用main()测试,文件相对路径为当前工程
-
*/
-
@Test
-
public void testWordCount() {
-
FileReader fr =
null;
-
BufferedWriter bw =
null;
-
try {
-
//1.创建Map集合
-
Map<Character, Integer> map =
new HashMap<Character, Integer>();
-
-
//2.遍历每一个字符,每一个字符出现的次数放到map中
-
fr =
new FileReader(
"dbcp.txt");
-
int c =
0;
-
while ((c = fr.read()) !=
-1) {
-
//int 还原 char
-
char ch = (
char) c;
-
// 判断char是否在map中第一次出现
-
if (map.
get(ch) ==
null) {
-
map.put(ch,
1);
-
}
else {
-
map.put(ch, map.
get(ch) +
1);
-
}
-
}
-
-
//3.把map中数据存在文件count.txt
-
//3.1 创建Writer
-
bw =
new BufferedWriter(
new FileWriter(
"wordcount.txt"));
-
-
//3.2 遍历map,再写入数据
-
Set<Map.Entry<Character, Integer>> entrySet = map.entrySet();
-
for (Map.Entry<Character, Integer> entry : entrySet) {
-
switch (entry.getKey()) {
-
case
' ':
-
bw.write(
"空格=" + entry.getValue());
-
break;
-
case
'\t':
//\t表示tab 键字符
-
bw.write(
"tab键=" + entry.getValue());
-
break;
-
case
'\r':
//
-
bw.write(
"回车=" + entry.getValue());
-
break;
-
case
'\n':
//
-
bw.write(
"换行=" + entry.getValue());
-
break;
-
default:
-
bw.write(entry.getKey() +
"=" + entry.getValue());
-
break;
-
}
-
bw.newLine();
-
}
-
}
catch (IOException e) {
-
e.printStackTrace();
-
}
finally {
-
//4.关流
-
if (fr !=
null) {
-
try {
-
fr.close();
-
}
catch (IOException e) {
-
e.printStackTrace();
-
}
-
-
}
-
if (bw !=
null) {
-
try {
-
bw.close();
-
}
catch (IOException e) {
-
e.printStackTrace();
-
}
-
-
}
-
}
-
-
}
-
}
六:转换流
转换流提供了在字节流和字符流之间的转换Java API 提供了两个转换流:InputStreamReader :将 InputStream 转换为 ReaderOutputStreamWriter :将 Writer 转换为 OutputStream字节流中的数据都是字符时,转成字符流操作更高效。很多时候我们使用转换流来处理文件乱码问题。实现编码和解码的功能。
* 处理流之二:转换流的使用 * 1.转换流:属于字符流 * InputStreamReader:将一个字节的输入流转换为字符的输入流 * OutputStreamWriter:将一个字符的输出流转换为字节的输出流 * * 2.作用:提供字节流与字符流之间的转换 * * 3. 解码:字节、字节数组 --->字符数组、字符串 * 编码:字符数组、字符串 ---> 字节、字节数组 * * * 4.字符集 *ASCII:美国标准信息交换码。 用一个字节的7位可以表示。 ISO8859-1:拉丁码表。欧洲码表 用一个字节的8位表示。 GB2312:中国的中文编码表。最多两个字节编码所有字符 GBK:中国的中文编码表升级,融合了更多的中文文字符号。最多两个字节编码 Unicode:国际标准码,融合了目前人类使用的所有字符。为每个字符分配唯一的字符码。所有的文字都用两个字节来表示。 UTF-8:变长的编码方式,可用1-4个字节来表示一个字符。
6.1:转换流的案例
-
ublic
class InputStreamReaderTest {
-
-
/*
-
此时处理异常的话,仍然应该使用try-catch-finally
-
InputStreamReader的使用,实现字节的输入流到字符的输入流的转换
-
*/
-
@Test
-
public void test1() throws IOException {
-
-
FileInputStream fis =
new FileInputStream(
"dbcp.txt");
-
// InputStreamReader isr = new InputStreamReader(fis);//使用系统默认的字符集
-
//参数2指明了字符集,具体使用哪个字符集,取决于文件dbcp.txt保存时使用的字符集
-
InputStreamReader isr =
new InputStreamReader(fis,
"UTF-8");
//使用系统默认的字符集
-
-
char[] cbuf =
new
char[
20];
-
int len;
-
while((len = isr.read(cbuf)) != -
1){
-
String str =
new String(cbuf,
0,len);
-
System.out.print(str);
-
}
-
-
isr.close();
-
-
}
-
-
/*
-
此时处理异常的话,仍然应该使用try-catch-finally
-
-
综合使用InputStreamReader和OutputStreamWriter
-
*/
-
@Test
-
public void test2() throws Exception {
-
//1.造文件、造流
-
File file1 =
new File(
"dbcp.txt");
-
File file2 =
new File(
"dbcp_gbk.txt");
-
-
FileInputStream fis =
new FileInputStream(file1);
-
FileOutputStream fos =
new FileOutputStream(file2);
-
-
InputStreamReader isr =
new InputStreamReader(fis,
"utf-8");
-
OutputStreamWriter osw =
new OutputStreamWriter(fos,
"gbk");
-
-
//2.读写过程
-
char[] cbuf =
new
char[
20];
-
int len;
-
while((len = isr.read(cbuf)) != -
1){
-
osw.write(cbuf,
0,len);
-
}
-
-
//3.关闭资源
-
isr.close();
-
osw.close();
-
-
-
}
七:标准输入、输出流
1.标准的输入、输出流 1.1 System.in:标准的输入流,默认从键盘输入 System.out:标准的输出流,默认从控制台输出 1.2 System类的setIn(InputStream is) / setOut(PrintStream ps)方式重新指定输入和输出的流。 1.3练习: 从键盘输入字符串,要求将读取到的整行字符串转成大写输出。然后继续进行输入操作, 直至当输入“e”或者“exit”时,退出程序。 方法一:使用Scanner实现,调用next()返回一个字符串 方法二:使用System.in实现。System.in ---> 转换流 ---> BufferedReader的readLine()
public static void main(String[] args) { BufferedReader br = null; try { InputStreamReader isr = new InputStreamReader(System. in); br = new BufferedReader(isr); while ( true) { System. out.println( "请输入字符串:"); String data = br.readLine(); if ( "e".equalsIgnoreCase( data) || "exit".equalsIgnoreCase( data)) { System. out.println( "程序结束"); break; } String upperCase = data.toUpperCase(); System. out.println(upperCase); } } catch (IOException e) { e.printStackTrace(); } finally { if (br != null) { try { br.close(); } catch (IOException e) { e.printStackTrace(); } } }7.1:小练习
Create a program named MyInput.java: Contain the methods for reading int,double, float, boolean, short, byte and String values from the keyboard.
import java.io.*; public class MyInput { // Read a string from the keyboard public static String readString() { BufferedReader br = new BufferedReader( new InputStreamReader(System.in)); // Declare and initialize the string String string = ""; // Get the string from the keyboard try { string = br.readLine(); } catch (IOException ex) { System.out.println(ex); } // Return the string obtained from the keyboard return string; } // Read an int value from the keyboard public static int readInt() { return Integer.parseInt(readString()); } // Read a double value from the keyboard public static double readDouble() { return Double.parseDouble(readString()); } // Read a byte value from the keyboard public static double readByte() { return Byte.parseByte(readString()); } // Read a short value from the keyboard public static double readShort() { return Short.parseShort(readString()); } // Read a long value from the keyboard public static double readLong() { return Long.parseLong(readString()); } // Read a float value from the keyboard public static double readFloat() { return Float.parseFloat(readString()); } }
八:打印流以及数据流8及
一打8
打印流: PrintStream 和 PrintWriter提供了一系列重载的 print() 和 println() 方法,用于多种数据类型的输出PrintStream 和 PrintWriter 的输出不会抛出 IOException 异常PrintStream 和 PrintWriter 有自动 flush 功能PrintStream 打印的所有字符都使用平台的默认字符编码转换为字节。在需要写入字符而不是写入字节的情况下,应该使用 PrintWriter 类。System.out 返回的是 PrintStream 的实例
-
PrintStream ps =
null;
-
try {
-
FileOutputStream fos =
new FileOutputStream(
new File(
"a.txt"));
-
// 创建打印输出流,设置为自动刷新模式(写入换行符或字节 '\n' 时都会刷新输出缓冲区)
-
ps =
new PrintStream(fos,
true);
-
if (ps !=
null) {
// 把标准输出流(控制台输出)改成文件
-
System.setOut(ps);
-
}
-
-
-
for (
int i =
0; i <=
255; i++) {
// 输出ASCII字符
-
System.
out.print( i);
//输出在a.txt的文件上
-
if (i %
50 ==
0) {
// 每50个数据一行
-
System.
out.println();
// 换行
-
}
-
}
-
-
-
}
catch (FileNotFoundException e) {
-
e.printStackTrace();
-
}
finally {
-
if (ps !=
null) {
-
ps.close();
-
}
-
}
数据流
3. 数据流 3.1 DataInputStream 和 DataOutputStream 3.2 作用:用于读取或写出基本数据类型的变量或字符串 练习:将内存中的字符串、基本数据类型的变量写出到文件中。 注意:处理异常的话,仍然应该使用 try- catch- finally. */ @Test public void test3() throws IOException { //1. DataOutputStream dos = new DataOutputStream( new FileOutputStream( "data.txt")); //2. dos.writeUTF( "刘建辰"); dos.flush(); //刷新操作,将内存中的数据写入文件 dos.writeInt( 23); dos.flush(); dos.writeBoolean( true); dos.flush(); //3. dos.close(); } /* 将文件中存储的基本数据类型变量和字符串读取到内存中,保存在变量中。 注意点:读取不同类型的数据的顺序要与当初写入文件时,保存的数据的顺序一致! */ @Test public void test4() throws IOException { //1. DataInputStream dis = new DataInputStream( new FileInputStream( "data.txt")); //2. String name = dis.readUTF(); int age = dis.readInt(); boolean isMale = dis.readBoolean(); System.out.println( "name = " + name); System.out.println( "age = " + age); System.out.println( "isMale = " + isMale); //3. dis.close(); }
九:对象流
印流流
凡是实现 Serializable 接口的类都有一个表示序列化版本标识符的静态变量:private static final long serialVersionUID;serialVersionUID 用来表明类的不同版本间的兼容性。 简言之,其目的是以序列化对象进行版本控制,有关各版本反序列化时是否兼容。如果类没有显示定义这个静态常量,它的值是 Java 运行时环境根据类的内部细节自动生成的。 若类的实例变量做了修改, serialVersionUID 可能发生变化。 故建议,显式声明。简单来说, Java 的序列化机制是通过在运行时判断类的 serialVersionUID 来验证版本一致性的。在进行反序列化时, JVM 会把传来的字节流中的serialVersionUID 与本地相应实体类的 serialVersionUID 进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。 (InvalidCastException)
9.1:案例
-
* 对象流的使用
-
*
1.ObjectInputStream 和 ObjectOutputStream
-
*
2.作用:用于存储和读取基本数据类型数据或对象的处理流。它的强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。
-
*
-
*
3.要想一个java对象是可序列化的,需要满足相应的要求。见Person.java
-
*
-
*
4.序列化机制:
-
* 对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种
-
* 二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。
-
* 当其它程序获取了这种二进制流,就可以恢复成原来的Java对象。
-
-
*
-
*
@author shkstart
-
*
@create
2019 上午
10:
27
-
*/
-
public
class ObjectInputOutputStreamTest {
-
-
/*
-
序列化过程:将内存中的java对象保存到磁盘中或通过网络传输出去
-
使用ObjectOutputStream实现
-
*/
-
@Test
-
public void testObjectOutputStream() throws IOException {
-
ObjectOutputStream oos=
null;
-
-
try {
-
oos =
new ObjectOutputStream(
new FileOutputStream(
"object.dat"));
-
//2.
-
oos.writeObject(
new String(
"我爱北京天安门"));
-
oos.flush();
//刷新操作
-
-
oos.writeObject(
new Person(
"王铭",
23));
-
oos.flush();
-
-
oos.writeObject(
new Person(
"张学良",
23,
1001,
new Account(
5000)));
-
oos.flush();
-
System.out.println(
"传输完成");
-
-
}
catch (IOException e) {
-
e.printStackTrace();
-
}
finally {
-
if(oos !=
null){
-
//3.
-
try {
-
oos.close();
-
}
catch (IOException e) {
-
e.printStackTrace();
-
}
-
-
}
-
}
-
-
}
-
}
-
/*
-
反序列化:将磁盘文件中的对象还原为内存中的一个java对象
-
使用ObjectInputStream来实现
-
*/
-
@Test
-
public void testObjectInputStream () throws IOException, ClassNotFoundException {
-
-
ObjectInputStream ois =
null;
-
try {
-
ois =
new ObjectInputStream(
new FileInputStream(
"object.dat"));
-
-
Object obj = ois.readObject();
-
String str = (String) obj;
-
-
Person p = (Person) ois.readObject();
-
Person p1 = (Person) ois.readObject();
-
-
System.out.println(str);
-
System.out.println(p);
-
System.out.println(p1);
-
-
}
catch (IOException e) {
-
e.printStackTrace();
-
}
catch (ClassNotFoundException e) {
-
e.printStackTrace();
-
}
finally {
-
if (ois !=
null) {
-
try {
-
ois.close();
-
}
catch (IOException e) {
-
e.printStackTrace();
-
}
-
-
}
-
}
序列化和反序列化里面的内容一一对应,
十:随机存取文件流
* RandomAccessFile的使用 * 1.RandomAccessFile直接继承于java.lang.Object类,实现了DataInput和DataOutput接口 * 2.RandomAccessFile既可以作为一个输入流,又可以作为一个输出流 * * 3.如果RandomAccessFile作为输出流时,写出到的文件如果不存在,则在执行过程中自动创建。 * 如果写出到的文件存在,则会对原有文件内容进行覆盖。(默认情况下,从头覆盖) * * 4. 可以通过相关的操作,实现RandomAccessFile“插入”数据的效果
@Test public void test1() { RandomAccessFile raf1 = null; RandomAccessFile raf2 = null; try { //1. raf1 = new RandomAccessFile( new File( "爱情与友情.jpg"), "r"); raf2 = new RandomAccessFile( new File( "爱情与友情1.jpg"), "rw"); //2. byte[] buffer = new byte[ 1024]; int len; while((len = raf1.read(buffer)) != - 1){ raf2.write(buffer, 0,len); } } catch (IOException e) { e.printStackTrace(); } finally { //3. if(raf1 != null){ try { raf1.close(); } catch (IOException e) { e.printStackTrace(); } } if(raf2 != null){ try { raf2.close(); } catch (IOException e) { e.printStackTrace(); } } } } @Test public void test2() throws IOException { RandomAccessFile raf1 = new RandomAccessFile( "hello.txt", "rw"); //abcxxxdef raf1.seek( 3); //将指针调到角标为3的位置 raf1.write( "xyz".getBytes()); //abcxyzdef //从指定的位置开始覆盖,默认从头部开始 raf1.close(); }10.1 案例
将hello.txt里面的内容:"abcdef",插入"xyz",变成abcxyzdef
public void test3() throws IOException { RandomAccessFile raf1 = new RandomAccessFile( "hello.txt", "rw"); raf1.seek( 3); //将指针调到角标为3的位置 //保存指针3后面的所有数据到StringBuilder中 StringBuilder builder = new StringBuilder(( int) new File( "hello.txt").length()); byte[] buffer = new byte[ 20]; int len; while(( len = raf1.read(buffer)) != -1){ builder. append( new String(buffer, 0, len)) ; } //调回指针,写入“xyz” raf1.seek( 3); raf1.write( "xyz".getBytes()); //将StringBuilder中的数据写入到文件中 raf1.write(builder.toString().getBytes()); raf1. close();
十一:Java NIO
10.1:常用方法
转载:https://blog.csdn.net/weixin_46443325/article/details/115475880
查看评论