总结:
1.java的io包括:
1.1文件流(操作字节)
1.2.字符流(操作字符(纯文本文件))
1.3.缓冲流(效率最高)
//1.创建输入/输出文件
//2.创建文件输入/输出流
//3.创建缓冲输入/输出流
//4.每个读取多少个字节数
//5.实际读取的字节数
//6.循环读写
1.4.对象流(操作对象(对象需要序列化))
2.从硬盘读取文件到内存中,步骤
2.1.创建读取文件
2.2.创建文件输入流
2.3.每次读取多少个字节
2.4.实际读取的字节数
2.5.循环读取
File file = new File("hello.txt");
FileInputStream fis = new FileInputStream(file);
byte[] b = new byte[20];
int len;
len=fis.read(b);
while(len != -1)
{
len=fis.read(b);
}
3.从内存中写字符流到文件中
3.1创建写入文件
3.2创建文件输出流
3.3写入字符流到文件中
File file = new File("hello.txt");
FileOutputStream fos = new FileOutputStream(file);
fos.write("zhangsan".getBytes());
4.实现文件复制,复制文件hello1.txt到hello2.txt,步骤
1.创建输入/输出文件
2.创建文件输入/输出流
3.每次读取多少个字节
4.实际读取到的个数
5.循环读写
File file1 = new File("hello1.txt");
File file2 = new File("hello.txt");
FileInputStream fis = new FileInputStream(file1);
FileOutputStream fos = new FileOutputStream(file2);
byte[] b = new byte[20];
int len = fis.read(b);
while(len != -1){
fos.write(b,0,len);
fos.flush();
len = fis.read(b);
}
I/O流用来处理设备之间的数据传输。
输入:读取外部数据(硬盘、磁盘等)到程序(内存)中。
输出:将程序(内存)数据输出到硬盘、光盘等设备中。
#1.FileInputStream
/**
* 从硬盘存在的一个文件中,读取其内容到内存中
* 使用FileInputStream
* @throws IOException
*/
@Test
public void testFile() {
FileInputStream fis = null;
try {
//1.创建一个文件对象
File file = new File("hello.txt");
//2.创建一个FileInputStream类的对象
fis = new FileInputStream(file);
//3.调用read()方法,实现文件的读取
int b = fis.read();
while (b != -1) {
//将int转成char显示出来
System.out.print((char)b);
b = fis.read();
}
} catch (Exception e) {
//抛出异常
}finally {
//4.关闭相应的流
try {
fis.close();
} catch (IOException e) {
// 关闭异常
e.printStackTrace();
}
}
}
#2.改善读取的效率
public void testFile() {
FileInputStream fis = null;
try {
//1.创建一个文件对象
File file = new File("hello.txt");
//2.创建一个FileInputStream类的对象
fis = new FileInputStream(file);
//3.定义一个数组,用于表示每次读取多少个数据
byte[] b = new byte[5];
//4.每次读入到byte[]中数据的是实际个数
int len;
//5.调用read()方法,实现文件的读取
len = fis.read(b);
while (len != -1) {
String str = new String(b, 0, len);
System.out.println(str);
len = fis.read(b);
}
} catch (Exception e) {
//抛出异常
}finally {
//4.关闭相应的流
try {
if (fis != null) {
fis.close();
}
} catch (IOException e) {
// 关闭异常
e.printStackTrace();
}
}
}
#3.FileOutputStream
/**
* 从内存中取出字节流到文件中
* 使用FileOutputStream
* @throws IOException
*/
@Test
public void testFileOutputStream() throws IOException{
//1.创建文件对象
//输出的物理文件可以不存在,执行过程中,
//若不存在,则会自动创建;若存在,则会将现有文件覆盖
File file = new File("hello.txt");
//2.创建一个文件输出流,用于写入数据到文件中
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file);
//3.写入数据到文件中
fos.write("zhangsanfeng".getBytes());
} catch (FileNotFoundException e) {
e.printStackTrace();
}finally {
if (fos != null) {
//4.关闭输出流
fos.close();
}
}
}
#4.文件复制
/**
* 从硬盘读取一个文件,并写入到另一个位置(相当于文件复制)
* @throws IOException
*/
@Test
public void testFileInputOutputStream() throws IOException{
//1.定义读出类文件
File file1 = new File("hello.txt");
//2.定义写入类文件
//注意:写入类文件在硬盘中不一定存在,会自动创建
File file2 = new File("hello2.txt");
//3.定义输入文件流:流入内存
FileInputStream fis = null;
//4.定义输出文件流:从内存输出
FileOutputStream fos = null;
try {
fis = new FileInputStream(file1);
fos = new FileOutputStream(file2);
//3.实现文件复制
byte[] b = new byte[20];
int len;
//循环读入到数组中
while ((len = fis.read(b)) != -1) {
//输出到文件中
fos.write(b, 0, len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}finally {
if (fis != null) {
fis.close();
}
if (fos != null) {
fos.close();
}
}
}
#5.字符流
使用FileReader、FileWriter可以实现文本文件(字符流)的复制。
对于非文本文件(音频、视频、图片等)只能使用字节流。
@Test
public void testFileReaderWriter() throws IOException{
FileReader fr = null;
FileWriter fw = null;
File src = new File("hello.txt");
File desc = new File("hello2.txt");
try {
fr = new FileReader(src);
fw = new FileWriter(desc);
char[] c = new char[24];
int len;
while ((len = fr.read(c)) != -1) {
fw.write(c, 0, len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}finally {
if (fr != null) {
fr.close();
}
if (fw != null) {
fw.close();
}
}
}
#6.缓冲流
缓冲流可以提升效率,平时一般用这个居多。
public void testBufferInputOutputStream() throws IOException{
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
//1.创建文件
File file1 = new File("hello.txt");
File file2 = new File("hello2.txt");
//2.创建节点流
FileInputStream fis = new FileInputStream(file1);
FileOutputStream fos = new FileOutputStream(file2);
//3.创建缓冲流
bis = new BufferedInputStream(fis);
bos = new BufferedOutputStream(fos);
//4.实现文件复制
byte[] b = new byte[2014];
int len;
while((len = bis.read(b)) != -1)
{
bos.write(b, 0, len);
//刷新
bos.flush();
}
} catch (Exception e) {
// TODO: handle exception
}finally {
if (bos != null) {
bos.close();
}
if (bis != null) {
bis.close();
}
}
}
#7.标准输入/输出流
标准的输入流:System.in
标准的输出流:System.out
/**
* 标准输入流:System.out
* 标准输出流:System.in
*
* 测试:从键盘输入字符串,要求将读取到的字符串输出,
* 接着继续输入,直到输入"exit"时退出程序
*/
@Test
public void testOtherStream() {
//缓冲流
BufferedReader br = null;
try {
InputStream is = System.in;
InputStreamReader isr = new InputStreamReader(is);
br = new BufferedReader(isr);
String str;
while (true) {
System.out.println("请输入字符串:");
str = br.readLine();
if (str.equals("exit")) {
break;
}
System.out.println(str);
}
} catch (Exception e) {
// TODO: handle exception
}finally {
}
}
#8.打印流
/**
* 打印流
*/
@Test
public void testPrintStream() {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(new File("print.txt"));
} catch (Exception e) {
// TODO: handle exception
}
//创建打印输出流,设置为自动刷新
PrintStream ps = new PrintStream(fos, true);
if (ps != null) {
//将标准的输出流(控制台)改成输出到文件
System.setOut(ps);
}
//输出字符
for (int i = 0; i < 255; i++) {
System.out.print(i);
if (i%50 == 0 ) {
System.out.println();
}
}
ps.close();
}
#9.对象流
ObjectInputStream:对象输入流
ObjectOutputStream:对象输出流
序列化:用ObjectOutputStream类将一个java对象写入文件
反序列化:用ObjectInputStream读取文件恢复java对象
对象流不能序列化static和transient修饰的成员变量。
/**
* 序列化对象
*1.该对象要实现Serializable接口
*2.对象里面的属性都需要实现Serializable接口
*/
class Car implements Serializable{
private static final long serialVersionUID = 1L;
Integer id;
String brand;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public Car(Integer id, String brand) {
super();
this.id = id;
this.brand = brand;
}
@Override
public String toString() {
return "Car [id=" + id + ", brand=" + brand + "]";
}
}
/**
* 对象的序列化过程
* 将内存中的对象通过ObjectOutputStream转换成二进制流,存储在硬盘中
* @throws ClassNotFoundException
*/
public static void main(String[] args) throws ClassNotFoundException {
Car car1 = new Car(1001, "ford");
Car car2 = new Car(1002, "audi");
ObjectOutputStream oos = null;
ObjectInputStream ois = null;
try {
//序列化对象存入硬盘
oos = new ObjectOutputStream(new FileOutputStream("hello.txt"));
oos.writeObject(car1);
oos.flush();
oos.writeObject(car2);
oos.flush();
//从硬盘中读取对象到内存
ois = new ObjectInputStream(new FileInputStream("hello.txt"));
//这里有多个对象,采取循环读取
Car car3 = (Car) ois.readObject();
System.out.println(car3);
Car car4 = (Car) ois.readObject();
System.out.println(car4);
}catch (IOException e) {
e.printStackTrace();
}finally{
try {
if (oos != null) {
oos.close();
}
if (ois != null) {
ois.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
#10.随机访问流
RandomAccessFile,该类支持随机访问的方式,程序可以直接跳到文件的任意位置来实现读/写文件。
/**
* RandomAccessFile:支持随机访问
* 1.既可以充当一个输入流,也可以充当一个输出流
* 2.支持从文件的任意位置读取、写入
* @throws IOException
*/
public static void main(String[] args) throws IOException {
RandomAccessFile rafRead = null;
RandomAccessFile rafWrite = null;
//文件的读写
try {
//读文件
rafRead = new RandomAccessFile(new File("hello.txt"), "r");
//写文件
rafWrite = new RandomAccessFile(new File("hello2.txt"), "rw");
byte[] b = new byte[20];
int len;
while ((len = rafRead.read(b)) != -1) {
rafWrite.write(b, 0, len);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
rafRead.close();
rafWrite.close();
}
}
实现文件内容覆盖的效果
//实现文件内容覆盖的效果
/**
* 如内容为:zhangwuji
* 现在实现用xy覆盖wu的效果
*/
RandomAccessFile raf = null;
try {
raf = new RandomAccessFile("hello.txt", "rw");
//指定覆盖的起始位置
raf.seek(5);
//覆盖
raf.write("xy".getBytes());
} catch (Exception e) {
// TODO: handle exception
}finally{
raf.close();
}
实现在文件指定位置插入指定元素
//实现在文件指定位置插入指定元素
/**
* 例如:在zhangwuji字符串的g后面添加上xy字符串,结果是zhangxywuji
*/
RandomAccessFile raf = null;
raf = new RandomAccessFile(new File("hello.txt"), "rw");
//1.现将指针移到第5个位置,即g的后面
raf.seek(5);
//2.读取g后面一行字符串
String str = raf.readLine();
//输出内容为wuji
System.out.println(str);
//3.查看目前指针在哪个位置
long pointPos = raf.getFilePointer();
//指针的位置在该行字符串结尾
System.out.println(pointPos);
//4.重新将指针调回第5个位置
raf.seek(5);
//5.插入字符串,此时字符串应该是zhangxyji
raf.write("xy".getBytes());
//6.查看目前指针的位置
long pointPos2 = raf.getFilePointer();
//此时指针的位置在y的后面
System.out.println(pointPos2);
//7.再插入字符串,字符串str肯定比zhangxy后面的字符串长,所以可以完全覆盖
raf.write(str.getBytes());
如上可以实现单行的插入,假设字符串存在多行呢
public static void main(String[] args) throws IOException {
//实现在文件指定位置插入指定元素(通用方法)
/**
* 多行字符串的插入
* 例如:在zhangwuji
* abcd
* 123456
* 需求:在字符串zhangwuji的g后面添加上xy字符串,结果是zhangxywuji,同时不改变字符串abcd和123456的位置
*/
RandomAccessFile raf = null;
raf = new RandomAccessFile(new File("hello.txt"), "rw");
raf.seek(5);
byte[] b = new byte[20];
int len;
StringBuffer sb = new StringBuffer();
while ((len = raf.read(b)) != -1) {
sb.append(new String(b,0,len));
}
//此处输出内容
/**
* gwuji
* abcd
* 123456
*/
System.out.println(sb.toString());
//查看指针,很明显在最后一个字符串的最有一个位置
long pointFile = raf.getFilePointer();
System.out.println(pointFile);
//调回指针
raf.seek(5);
//写入字符串,此时指针在y的后面
raf.write("xy".getBytes());
//拼接后面的字符串,得出的结果就是
/**
* zhangxywuji
* abcd
* 123456
*/
raf.write(sb.toString().getBytes());
//关闭流
raf.close();
}