IO流
- 解决数据的输入输出问题
File类的使用
- java.io.File类:文件和文件目录路径的抽象表示形式
- File对象可以作为参数传递给流的构造器
package file;
import org.testng.annotations.Test;
import java.io.File;
import java.io.IOException;
import java.util.Date;
/*
File类的使用
1.File类的一个对象,代表一个文件或者一个文件目录(文件夹)
路径分隔符和系统有关:
windows和DOS系统默认使用"\"来表示
UNIX和URL使用"/"来表示
java中提供了一个常量:public static final String separator,File.separator根据系统不同动态提供分隔符
File的常用方法:
public String getAbsolutePath():获取绝对路径
public String getPath():获取路径
public String getName():获取名称
public String getParent():获取上层文件目录路径,若无,返回null
public long length():获取文件长度(字节数),不能获取目录的长度
public long lastModified():获取最后一次的修改时间,毫秒值
以下方法适用文件目录:
public String[] list():获取指定目录下的所有文件或文件目录的名称数组
public File[] listFiles():获取指定目录下的所有文件或者文件目录的File数组
*/
/*
public boolean renameTo(File dest):把文件重命名为指定的文件路径
比如:file1.renameTo(file2):
要想返回true,要保证file1在硬盘中存在,且file2不能在硬盘中存在
*/
/*
public boolean isDirectory():判断是否是文件目录
public boolean isFile():判断是否是文件
public boolean exists():判断是否存在
public boolean canRead():判断是否可读
public boolean canWrite():判断是否可写
public boolean isHidden():判断是否隐藏
创建硬盘中对应的文件或文件目录:
public boolean createNewFile():创建文件,若文件不在则不创建,返回false
public boolean mkdir():创建文件目录,若文件目录存在则不创建,如果此文件目录上层文件目录不存在,则不创建
public boolean mkdirs():创建文件目录,如果上层文件目录不存在,一并创建
删除硬盘中的文件或文件目录:
public boolean delete():删除文件或者文件夹
删除注意事项:java中的删除不走回收站
*/
public class FileTest {
/*
如何创建File的实例化:
1.相对路径:相较于某个路径下指明的路径
2.绝对路径:包含盘符在内的文件或文件目录的路径
*/
@Test
public void test(){
//构造器1:创建文件
File file = new File("hello.txt");//相对于当前的module
File file1 = new File("D:\\Java\\exercise2\\he.txt");//绝对路径
System.out.println(file);
System.out.println(file1);
//构造器2:创建exercise2文件夹
File file2 = new File("D:\\Java", "exercise2");
System.out.println(file2);
//构造器3:exercise2下的文件
File file3 = new File(file2, "hi,txt");
System.out.println(file3);
}
@Test
public void test1(){
File file = new File("hello.txt");
File file1 = new File("D:\\io\\hi.txt");
System.out.println(file.getAbsolutePath());
System.out.println(file.getPath());
System.out.println(file.getName());
System.out.println(file.getParent());//获取上层文件目录,无返回null
System.out.println(file.length());
System.out.println( new Date(file.lastModified()));//最近修改时间
System.out.println("===============");
System.out.println(file1.getAbsolutePath());
System.out.println(file1.getPath());
System.out.println(file1.getName());
System.out.println(file1.getParent());
System.out.println(file1.length());
System.out.println(file1.lastModified());
}
@Test
public void test3(){
//找文件名
File file = new File("D:\\Java\\exercise2\\src");
String[] list = file.list();
for (String s : list) {
System.out.println(s);
}
//找完整名包括路径
File[] files = file.listFiles();
for (File file1 : files) {
System.out.println(file1);
}
}
/*
public boolean renameTo(File dest):把文件重命名为指定的文件路径
比如:file1.renameTo(file2):
要想返回true,要保证file1在硬盘中存在,且file2不能在硬盘中存在
*/
@Test
public void test4(){
File file1 = new File("hello.txt");
File file2 = new File("D:\\io\\hi.txt");
boolean renameTo = file1.renameTo(file2);
System.out.println(renameTo);
}
/*
public boolean isDirectory():判断是否是文件目录
public boolean isFile():判断是否是文件
public boolean exists():判断是否存在
public boolean canRead():判断是否可读
public boolean canWrite():判断是否可写
public boolean isHidden():判断是否隐藏
*/
@Test
public void test5(){
File file = new File("hello.txt");
System.out.println(file.exists());//先判断在不在
System.out.println(file.isFile());
System.out.println(file.isDirectory());
System.out.println(file.isHidden());
System.out.println(file.canRead());
System.out.println(file.canWrite());
}
/*
创建硬盘中对应的文件或文件目录:
public boolean createNewFile():创建文件,若文件不在则不创建,返回false
public boolean mkdir():创建文件目录,若文件目录存在则不创建,如果此文件目录上层文件目录不存在,则不创建
public boolean mkdirs():创建文件目录,如果上层文件目录不存在,一并创建
删除硬盘中的文件或文件目录:
public boolean delete():删除文件或者文件夹
删除注意事项:java中的删除不走回收站
*/
@Test
public void test6() throws IOException {
//文件的创建
File file = new File("hi.txt");
if (!file.exists()){
file.createNewFile();
System.out.println("创建成功");
}else{//文件存在
file.delete();
System.out.println("删除成功");
}
//文件目录的创建
File file1 = new File("D:\\io\\io1\\io2");
boolean mkdir = file1.mkdir();//不会创建上层目录
if (mkdir){
System.out.println("创建成功1");
}
File file2 = new File("D:\\io\\io1\\io2");
boolean mkdirs = file2.mkdirs();//会创建上层目录
if (mkdirs) {
System.out.println("创建成功2");
}
}
}
练习题
package file;
import org.testng.annotations.Test;
import java.io.File;
import java.io.IOException;
public class FileExercise {
@Test
public void test() throws IOException {
File file = new File("D:\\io\\io1\\hello.txt");
//创建一个与file同目录下的另外一个文件,文件名为:haha.txt
File destFile = new File(file.getParent(), "haha.txt");//内存层面的
boolean newFile = destFile.createNewFile();
if (newFile){
System.out.println("创建成功");
}
}
//判断指定目录下是否有后缀名为.jpg的文件,如果有就输出该文件名称
@Test
public void test1(){
File file = new File("D:\\io\\io1");
String[] list = file.list();
for (String s : list) {
if (s.endsWith("jpg")){
System.out.println(s);
}
}
}
//递归:文件目录
//打印除指定目录所有文件名称,包含子文件目录中的文件
public static void printSubFile(File dir){
//打印目录子文件
File[] subFiles = dir.listFiles();
for (File f : subFiles) {
if (f.isDirectory()){//判断是否是文件目录
printSubFile(f);
}else {//如果是文件
System.out.println(f.getAbsolutePath());
}
}
}
//求指定目录所在空间的大小
public long getDirectorySize(File file){
//file是文件,直接返回file.length()
//file是文件目录,把它的下一级所有大小加起来就是总大小
long size = 0;
if (file.isFile()){
size += file.length();
}else {
File[] all = file.listFiles();//获取下一级
//累加all[i]的大小
for (File f : all) {
size += getDirectorySize(f);//f的大小
}
System.out.println(size);
}
return size;
}
//测试
public static void main(String[] args) {
//File dir = new File("D:\\Java\\exercise2\\src");
//printSubFile(dir);
File file = new File("D:\\io\\io1");
FileExercise fileExercise = new FileExercise();
fileExercise.getDirectorySize(file);
}
}
IO流原理及流的分类
-
处理设备之间的数据传输,以“流”的方式进行数据输入/输出
-
输入:读取外部数据(文件,网络)到程序(内存)当中,
-
输出:将程序(内存)数据输出到磁盘、光盘等存储设备中
流的分类
-
按操作数据单位不同分为:字节流(8 bit),字符流(16 bit)
-
按数据流的流向不同分为:输入流,输出流
-
按流的角色不同分为:节点流(文件–内存,作用在文件上的流),处理流(在节点流上包了一层流,将节点流的对象作为属性传输)
-
字符流不能处理图片文件的测试
-
抽象基类 字节流 字符流 输入流 InputStream后缀 Reader 输出流 OutputStream后缀 Writer
流的体系结构
-
//1.File类的实例化
//2.FileReader流的实例化
//3.读入的操作
//4.资源的关闭
package io;
import org.testng.annotations.Test;
import java.io.*;
/*
一、流的分类
按操作数据单位不同分为:字节流(8 bit),字符流(16 bit)
按数据流的流向不同分为:输入流,输出流
按流的角色不同分为:节点流,处理流
二、流的体系结构
二、流的体系结构
抽象基类 节点流(文件流) 缓冲流(处理流的一种)
InputStream FileInputStream(read(byte[] buffer)) BufferInputStream(read(byte[] buffer)
OutputStream FileOutputStream(write(byte[] buffer,0,len)) BufferOutputStream(write(byte[] buffer,0,len)/flush()
Reader FileReader(read(char[] cbuf)) BufferReader(read(char[] cbuf)/readline())
Writer FileWriter(write(char[] cbuf,0,len)) BufferWriter(char[] cbuf,0,len) /flush()
缓存流中都有flush()操作,将数据刷出去
*/
public class FileReaderWriterTest {
/*
将exercise2下的hello.txt文件内容读入程序中,并输出到控制台
1.read():返回读入的一个字符,如果达不到文件末尾,返回-1
2.抛出异常的方式不可取,会造成流的关闭操作不执行,造成内存的浪费,
用try-catch-finally方法:ctrl+alt+t
3.读入的文件一定要存在,否则就会报:FileNotFoundException异常
*/
@Test
public void testFileReader() {
FileReader fr = null;
try {
//main方法里面是相较于工程下,而test是相较于模块下
//1.实例化File类的对象,指明要操作的文件
File file = new File("hello.txt");//相较于当前module
//2.提供具体的流,流的实例化
fr = new FileReader(file);
//3.数据的读入过程
//read():返回读入的一个字符,如果达不到文件末尾,返回-1
int data;
while((data = fr.read())!=-1){
System.out.print((char) data);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
}
//4.流的关闭操作
//物理连接,如数据库连接,输入输出流,Socket连接需要手动关闭,避免内存泄漏
try {
if (fr != null)
fr.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
//对read()方法的升级,read的重载方法
@Test
public void test1() {
FileReader fr = null;
try {
//1.File类的实例化
File file = new File("hello.txt");
//2.FileReader流的实例化
fr = new FileReader(file);
//3.读入的操作
//read(char[] cbuffer):返回每次读入cubffer数组中的字符个数,如果到达文件末尾返回-1
// 如果是字节类型,就是byte类型
char[] cbuf = new char[5];//返回读入的5个字符
int len;
while((len = fr.read(cbuf)) != -1){
//方式一
for (int i = 0; i < len; i++) {//i<len:每次读进去几个就写几个
System.out.print(cbuf[i]);
}
//方式二(不推荐)
// String str = new String(cbuf, 0, len);
// System.out.print(str);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
}
//4.资源的关闭
try {
if (fr != null)
fr.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
/*
从内存中写出数据到硬盘的文件里
说明:
1.输出操作,对应的File文件可以不存在,并不会报异常
2.
如果不存在,在输出的过程中,会自动创建此文件
如果存在,
如果使用的构造器是:FileWriter(file,false)/FileWriter(file):对原文件覆盖
如果使用的构造器是:FileWriter(file,true),对原文件续写
*/
//写出
@Test
public void testFileWriter() {
FileWriter fw = null;
try {
//1.提供file类的对象,指明写出到的文件
File file = new File("hello1.txt");
//2.提供FileWriter的对象,用于数据的写出
fw = new FileWriter(file);
//3.写出的操作
fw.write("I have a dream" +"\n");
fw.write("you have a dream");
} catch (IOException e) {
e.printStackTrace();
} finally {
}
//4.资源的关闭
try {
if (fw != null)
fw.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
@Test
public void testFileReaderFileWriter() {
FileReader fr = null;
FileWriter fw = null;
try {
//1.创建File类的对象,指明读入和写出的文件
File file1 = new File("hello.txt");
File file2 = new File("hello2.txt");
//2.创建输入流和输出流的对象
fr = new FileReader(file1);
fw = new FileWriter(file2);
//3.数据的读入和写出
char[] cbuf = new char[5];
int len;//记录每次读入到cubf数组中的字符的个数
while ((len = fr.read(cbuf)) != -1){
for (int i = 0; i < len; i++) {
System.out.print(cbuf[i]);
}
//每次写出len个字符
fw.write(cbuf,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
}
//4.关闭资源
try {
if (fr != null)
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fw != null)
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
package io;
import org.testng.annotations.Test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/*
测试FileInputStream和FileOutputStream的使用
结论:
对于文本文件(txt,java,c,cpp),使用字符流处理
对于非文本文件(jpg,mp3,mp4,doc,ppt,avi),使用字节流处理
*/
public class FileInputOutputStreamTest {
@Test
public void testFileInputStream() {
FileInputStream fis = null;
try {
//1.创建文件
File file = new File("hello.txt");
//2.创建流
fis = new FileInputStream(file);
//3.读数据
byte[] buffer = new byte[5];
int len;
while((len = fis.read(buffer)) != -1){
String str = new String(buffer, 0, len);
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
}
//4.关闭资源
try {
if (fis !=null)
fis.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
}
- Buffer流的使用
package io;
import org.testng.annotations.Test;
import java.io.*;
public class BufferTest {
//实现文件复制的方法
public void copyFileWithBuffered(String srcPath,String destPth) {
BufferedOutputStream bos = null;
try {
//1.造文件
File srcFile = new File(srcPath);
File destFile = new File(destPth);
//2.造流
//2.1 造节点流
FileInputStream fis = new FileInputStream(srcFile);
FileOutputStream fos = new FileOutputStream(destFile);
//2.2 造缓冲流
BufferedInputStream bis = new BufferedInputStream(fis);
bos = new BufferedOutputStream(fos);
//3.复制的细节:读入、写出
byte[] buffer = new byte[1024];
int len;
while((len = bis.read(buffer)) != -1){
bos.write(buffer,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
}
//4.关闭资源
//关闭外层流的同时,内层流也会自动关闭
try {
if (bos != null)
bos.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
//使用BufferReader和BufferWriter实现文本文件的复制
@Test
public void test1() {
BufferedReader br = null;
BufferedWriter bw = null;
try {
//1.造文件造流,造缓冲流
br = new BufferedReader(new FileReader(new File("dbvp.txt")));
bw = new BufferedWriter(new FileWriter(new File("dbvp1.txt")));
//2.读写操作
//方式一
// char[] cbuf = new char[1024];
// int len;
// while ((len = br.read(cbuf)) != -1){
// bw.write(cbuf,0,len);
// }
//方式二
String data;
while((data = br.readLine()) != null){
bw.write(data + "\n");//data中不包含换行符,得自己加或者加:newLine();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
}
//3.关闭资源
try {
if (bw != null)
bw.close();
if (br != null)
br.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
}
练习题
- 对图片的加密解密操作
对数组buffer的数据异或了5,就是加密
对数组buffer的数据异或了5,再异或5就可以解密
package io;
import org.testng.annotations.Test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/*
对图片的加密解密操作
对数组buffer的数据异或了5,就是加密
对数组buffer的数据异或了5,再异或5就可以解密
*/
public class ExerciseTest {
//图片的加密
@Test
public void test(){
FileOutputStream fos = null;
try {
FileInputStream fis = new FileInputStream(new File("llyy.jpg"));
fos = new FileOutputStream(new File("llyysecret.jpg"));
byte[] buffer = new byte[20];
int len;
while ((len = fis.read(buffer))!= -1){
//对字节数据进行修改
//错误写法:没有对buffer中数据进行修改
// 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 {
}
try {
if (fos !=null)
fos.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
//解密
//对数组的数据异或了5,再异或5就可以解密
@Test
public void test1(){
FileOutputStream fos = null;
try {
FileInputStream fis = new FileInputStream(new File("llyy.jpg"));
fos = new FileOutputStream(new File("llyy1.jpg"));
byte[] buffer = new byte[20];
int len;
while ((len = fis.read(buffer))!= -1){
//对字节数据进行修改
//错误写法:没有对buffer中数据进行修改
// for (byte b : buffer) {
// b = (byte) (b ^ 5);
// }
//正确:
for (int i = 0; i < len; i++) {
buffer[i] = (byte) (buffer[i] ^ 5 ^5);
}
fos.write(buffer,0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
}
try {
if (fos !=null)
fos.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
}
- 获取文本上每个字符出现的次数(遍历文本每一个字符,字符及出现的次数保存在Map中:将Map中数据写入文件)
package io;
import org.testng.annotations.Test;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/*
获取文本上字符出现的次数,把数据写入文件
思路:
1.遍历文本每一个字符
2.字符出现的次数存在Map中
Map<Character,Integer> map = new HashMap(Character,Integer>();
map.put('a',18);
map.put('你',2);
3.把map中的数据写入文件
*/
public class ExerciseTest1 {
@Test
public void test(){
FileReader fr = null;
BufferedWriter bw = null;
try {
//1.创建map集合
HashMap<Character, Integer> map = new HashMap<>();
//2.遍历每一个字符,每一个字符出现的次数放到map中
fr = new FileReader("dbvp.txt");
int c = 0;
while ((c = fr.read())!= -1){
//int 还原为char
char ch = (char) c;
//判断char是否在map中第一次出现
if (map.get(ch) == null){//或者contains()
map.put(ch,1);
}else {
map.put(ch,map.get(ch)+1);
}
}
//3.把map中数据存在文件count.out
//3.1创建writer
bw = new BufferedWriter(new FileWriter(new File("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());
}
bw.newLine();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
}
try {
if (fr != null)
fr.close();
if (bw!=null)
bw.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
}
转换流
1.转换流:(字符流)
输入的字节流(byte)转换成字符流(char):InputStreamReader
输入的字符流(char)转换成字节流(byte):OutputStreamWriter
2.解码:字节、字节数组 —> 字符数组,字符串
编码:字节、字节数组 —> 字符数组,字符串
3.字符集
1.ASCII:标准信息交换码,用一个字节的7位可以表示
2.IS08859-1:拉丁码表,欧洲码表,用一个字节的8位表示
GB2312:中国的中文编码表,最多两个字节编码所有字符
GBK:中文编码表升级
Unicode:国际标准码,为每个字符分配唯一的字符码
UTF-8:变长的编码方式,可用1-4个字节表示一个字符
- Unicode字符集只是定义了字符的集合和唯一编码,
Unicode编码则是对UTF-8、UTF-16等具体编码方案的统称
package io;
import org.testng.annotations.Test;
import java.io.*;
/*
处理流的一种:
1.转换流:(字符流)
输入的字节流(byte)转换成字符流(char):InputStreamReader
输出的字符流(char)转换成字节流(byte):OutputStreamWriter
2. 解码:字节、字节数组 ---> 字符数组,字符串
编码:字节、字节数组 ---> 字符数组,字符串
3.字符集
1.ASCII:标准信息交换码,用一个字节的7位可以表示
2.IS08859-1:拉丁码表,欧洲码表,用一个字节的8位表示
GB2312:中国的中文编码表,最多两个字节编码所有字符
GBK:中文编码表升级
Unicode:国际标准码,为每个字符分配唯一的字符码
UTF-8:变长的编码方式,可用1-4个字节表示一个字符
Unicode字符集只是定义了字符的集合和唯一编码,
Unicode编码则是对UTF-8、UTF-16等具体编码方案的统称
*/
public class InputStreamReaderTest {
@Test
public void test() throws IOException {
File file = new File("dbvp.txt");
FileInputStream fis = new FileInputStream(file);
System.out.println(file.getAbsolutePath());
//InputStreamReader isr = new InputStreamReader(fis);//系统默认的字符集,UTF-8
//参数2指明了字符集,具体使用取决于文件保存时使用的字符集
java.io.InputStreamReader isr = new java.io.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();
}
}
其他流(输入输出流、打印流)
package io;
import org.testng.annotations.Test;
import java.io.*;
/*
System in :标准输入流,默认从键盘输入。类型是InputStream
System out:标准的输出流,默认从控制台输出,类型是PrintStream,是OutputStream的子类
*/
public class OtherStreamTest {
/*
练习题:
从键盘输入字符串,要求将读取到的整行字符串转成大写输出,用readline()读整行
然后继续输入操作,直至当输入"e"或者”exit“时,退出程序
*/
public static void main(String[] args) {
BufferedReader br = null;
try {
InputStreamReader isr = new InputStreamReader(System.in);
//转换成buffer
br = new BufferedReader(isr);
String data;
System.out.println("请输入字符串:");
while((data = br.readLine()) != null){
System.out.println("请输入字符串:");
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 {
}
try {
if (br!=null)
br.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
/*
打印流:
PrintStream和PrintWriter
提供一系列重载(参数不同)的print()和println()
*/
@Test
public void test(){
PrintStream ps = null;
try {
FileOutputStream fos = new FileOutputStream(new File("D:\\io\\text.txt"));
//创建打印输出流,设置自动刷新模式
ps = new PrintStream(fos, true);
if (ps != null){
System.setOut(ps);//把标准输出流(控制台输出)改成文件
}
for (int i = 0; i <= 255; i++) {
System.out.print((char) i);//打印ASCII字符
if (i % 50 == 0){//每50个一行
System.out.println();
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
}
try {
if (ps != null)
ps.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
/*
数据流的使用:
可以对基本数据类型和String类型做读写
*/
@Test
public void test1() throws IOException {
//写出
DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));
dos.writeUTF("刘想");
dos.flush();
dos.writeInt(23);
dos.flush();
dos.close();
}
@Test
public void test2() throws IOException {
//读入
//读取的顺序要与保存的数据顺序一致
DataInputStream dis = new DataInputStream(new FileInputStream("data.txt"));
String name = dis.readUTF();
int age = dis.readInt();
System.out.println("name=" + name);
System.out.println("age=" + age);
dis.close();
}
}
对象流
-
可以把java中的对象写入到数据源中,也能把对象从数据源中还原回来。
-
序列化:用(ObjectOutputStream)类保存基本类型数据或对象的机制
-
反序列化:用(ObjectInputStream)类读取基本类型数据或对象的机制
-
对象的序列化机制:允许内存中的java对象转换成平台无关的二进制流,从而允许把这种二进制流持续的保存在磁盘上,或通过网络将这种二进制流输到另一个网络节点,当其他程序获取了这种二进制流就可以恢复成原来的java对象
package io;
import org.testng.annotations.Test;
import java.io.*;
/*
对象流的使用:
1.ObjectInputStream\ObjectOutputStream
2.作用:用于存储和读取基本数据或对象的处理流,
String已经实现了Serializable可序列化
自定义的类要可序列化需要类继承接口,在当前类需要定义常量:
public static final long serialVersionUID = 42342424235L;//序列版本号
String和基本数据类型都是可序列化的
内部属性也必须可序列化
*/
public class ObjectInputOutputStreamTest {
//序列化过程:将内存中的java对象保存到磁盘中或通过网络传输出去
//使用ObjectOutputStream实现
@Test
public void testObjectOutputStream(){
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(new FileOutputStream("object.dat"));
oos.writeObject(new String("我爱yy"));//String已经实现了Serializable可序列化
oos.flush();
oos.writeObject(new Person("llx",23));//自定义的类要可序列化需要接口
oos.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
try {
if (oos!=null)
oos.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
//反序列化的过程:将磁盘文件中的对象还原为内存中的java对象
//使用ObjectInputStream
@Test
public void test1(){
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream("object.dat"));
Object obj = ois.readObject();
String str = (String) obj;
Person p = (Person) ois.readObject();
System.out.println(str);
System.out.println(p);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
}
try {
if (ois != null)
ois.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
}
package io;
import java.io.Serializable;
//自定义类
public class Person implements Serializable {
public static final long serialVersionUID = 423424242L;//序列版本号
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
随机存储文件流
package io;
import org.testng.annotations.Test;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
/*
随机存储文件流:
RandomAccessFile使用:
1.RandomAccessFile直接继承于java.lang.Object类,实现了DateInput和DateOutput接口
2.RandomAccessFile既可以作为一个输入流,又可以作为一个输出流
3.如果RandomAccessFile作为输出流时,写出到的文件如果不存在,则自动创建
如果写出的文件存在,则覆盖,从头覆盖
raf1.seek(3);//将指针调到指标为3的位置进行覆盖
4.可以通过StringBuilder实现插入效果(效率差)
构造器后缀:
-r:只以读的方式打开,不会创建文件
-rw:打开以便读取和写入
-rwd:打开以便读取和写入,同步文件内容的更新
-rws:打开以便读取和写入,同步文件内容和元件数的更新
*/
public class RandomAccessFileTest {
@Test
public void test() {
RandomAccessFile raf1 = null;
RandomAccessFile raf2 = null;
try {
raf1 = new RandomAccessFile(new File("llyy.jpg"), "r");
raf2 = new RandomAccessFile(new File("llyy1.jpg"), "rw");
byte[] buffer = new byte[1024];
int len;
while ((len = raf1.read(buffer)) != -1){
raf2.write(buffer,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
}
try {
if (raf1 != null)
raf1.close();
if (raf2 != null)
raf2.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
//实现覆盖的效果
@Test
public void test2() throws IOException {
File file = new File("hello.txt");
RandomAccessFile raf1 = new RandomAccessFile(file, "rw");
raf1.seek(file.length());//将指针调到末尾的位置进行拼接
raf1.write("xyz".getBytes());//覆盖操作
raf1.close();
}
//使用RandomAccessFile实现插入的效果
@Test
public void test3() throws IOException {
RandomAccessFile raf = new RandomAccessFile(new File("hello.txt"), "rw");
raf.seek(3);//将指针调到角标为3的位置
//保存指针3后面的所有数据到StringBuilder中
//buffer里的数据放到String里面
StringBuilder builder = new StringBuilder((int) new File("hello.txt").length());
byte[] buffer = new byte[20];
int len;
while ((len = raf.read(buffer)) != -1){
builder.append(new String(buffer,0,len));
}
//调回指针,写入”xyz“
raf.seek(3);
raf.write("xyz".getBytes());
//将StringBuilder中的数据写入到文件中
raf.write(builder.toString().getBytes());
raf.close();
}
}
1.close();
if (raf2 != null)
raf2.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
//实现覆盖的效果
@Test
public void test2() throws IOException {
File file = new File("hello.txt");
RandomAccessFile raf1 = new RandomAccessFile(file, "rw");
raf1.seek(file.length());//将指针调到末尾的位置进行拼接
raf1.write("xyz".getBytes());//覆盖操作
raf1.close();
}
//使用RandomAccessFile实现插入的效果
@Test
public void test3() throws IOException {
RandomAccessFile raf = new RandomAccessFile(new File("hello.txt"), "rw");
raf.seek(3);//将指针调到角标为3的位置
//保存指针3后面的所有数据到StringBuilder中
//buffer里的数据放到String里面
StringBuilder builder = new StringBuilder((int) new File("hello.txt").length());
byte[] buffer = new byte[20];
int len;
while ((len = raf.read(buffer)) != -1){
builder.append(new String(buffer,0,len));
}
//调回指针,写入”xyz“
raf.seek(3);
raf.write("xyz".getBytes());
//将StringBuilder中的数据写入到文件中
raf.write(builder.toString().getBytes());
raf.close();
}
}