1. File

目前程序运行之后的结果 (程序终止) 数据全部丢失。 都需要==持久化==保存程序运行之后的数据。

磁盘(文件) 内存/缓存(程序不能停)

==代表磁盘里面存在或者不存在的目录/文件== 操作文件/目录的属性。

 

==1.1 常用构造==

文件和目录路径名的抽象表示
File(String pathname)     文件/目录路径 转换File对象
File(File parent, String child)   指定父级目录+子级文件/目录 转换File对象  
File(String parent, String child)    

 

1.2 常用属性

static String pathSeparator  环境变量分割:  win: ;  unix:  :
static char pathSeparatorChar  
   
static String separator  代表系统的盘符分割  win \  unix: /    
static char separatorChar    D:\\a.txt  

 

==1.3 代表文件==

 private static void demo1() {

       //1. 创建文件对象
       //路径:
       //1. 绝对路径 D:\\a.txt   http://www.baidu.com
       //2. 相对路径 / 根路径   相对于project
       // D:\workspace\one\day18\src\a.txt
       // day18/src/a.txt


       String filePath = "day18/src/a.txt";
       File file = new File(filePath);

       //System.out.println(file);

       System.out.println("文件名称:" + file.getName());
       System.out.println("文件绝对路径:" + file.getAbsolutePath());
       System.out.println("文件相对路径:" + file.getPath());
       System.out.println("文件大小(字节个数):" + file.length());
       System.out.println("操作文件最新时间(毫秒数):" + new Date(file.lastModified()));

       //判断
       System.out.println("判断是否是一个文件:" + file.isFile());
       System.out.println("判断文件是否存在:" + file.exists());

       //文件权限
       //System.out.println("修改文件权限:"+file.setReadOnly());
       //System.out.println(file.canRead());
       //System.out.println(file.canExecute());

       //删除文件
       //System.out.println("删除文件:" + file.delete());

  }

 

 private static void demo2() {

       System.out.println(File.pathSeparator);// ;
       System.out.println(File.pathSeparatorChar);

       System.out.println(File.separator);// \
       System.out.println(File.separatorChar);

       File file = new File("day18"+File.separator+"demo1.txt");
       System.out.println(file.exists());
       //文件不存在 自动创建

       try {
           if (!file.exists()) {
               System.out.println("文件不存在 已经自动创建");
               file.createNewFile();
          }
      } catch (IOException e) {
           e.printStackTrace();
           System.out.println("创建文件 一定要保证 父级路径是存在的");
      }
  }

 

==1.4 代表目录==

private static void demo3() {

       //File 代表目录
       String path = "day18/src";
       //   / 相对路径
       File directory = new File(path);


       System.out.println(directory.getName());
       System.out.println(directory.getAbsolutePath());
       System.out.println(directory.getPath());

       System.out.println(new Date(directory.lastModified()));

       //判断
       System.out.println(directory.isDirectory());
       System.out.println(directory.exists());


  }

 

private static void demo4() {

       File dir = new File("day18/demo");

//       try {
//           if(!dir.exists()){
//               dir.createNewFile();
//           }
//       } catch (IOException e) {
//           e.printStackTrace();
//       }

       //mkdir() vs mkdirs()
       //mkdir: 创建1级目录
       //mkdirs(): >=1
       // System.out.println(dir.mkdirs());

       //删除目录: 没有子级资源 (删除空目录)
       System.out.println(dir.delete());
  }

 

1.5 查看目录子级

|-com
| |- javasm
| | |-exercise  
| | | |- Account.java
| | | |- Account.java
| | | |- Account.java    
| | |-file
| | | |- Account.java    
|-a.txt    
private static void selectChild1(File parentDir, String s) {
if (!parentDir.exists()) {
throw new RuntimeException("父级路径不存在的");
}
File[] files = parentDir.listFiles();
for (File child : files) {
System.out.println(s + child.getName());
if (child.isDirectory()) {
selectChild1(child, "| " + s);
}
}
}

 

 private static void selectChild2(File parent, String s) {

String[] child = parent.list();//获得1级资源名称
//子级是目录的----> File.isDirectory()

for (String name : child) {
System.out.println(s + name);
File childFile = new File(parent, name);
if (childFile.isDirectory()) {
selectChild2(childFile, "| " + s);
}
}

}

 

1.5 过滤子级资源

private static void selectChild2(File parent, String s) {
String[] child = parent.list();//获得1级资源名称
//子级是目录的----> File.isDirectory()
for (String name : child) {
File childFile = new File(parent, name);
if (childFile.isDirectory()) {//子级目录
System.out.println(s + name);
selectChild2(childFile, "| " + s);
} else {
//只展示文件后缀是java
if (name.endsWith("java")) {
System.out.println(s + name);
}
}
}
}

 

private static void filterChild(File parent, String s) {

//1级资源
// File[] files = parent.listFiles(new FileFilter() {
// @Override
// public boolean accept(File child) {
// if(child.isDirectory()){
// return true;
// }
// return child.getName().endsWith("java");
// }
// });

File[] files = parent.listFiles(child -> {
if (child.isDirectory()) {
return true;
}
return child.getName().endsWith("java");
});

for (File child : files) {
System.out.println(s + child.getName());
if (child.isDirectory()) {
filterChild(child, "| " + s);
}
}
}

 

 

 

2. IO

File类只能操作属性 无法操作文件里面的数据。 InputStream OutputStream

读: 程序读取文件里面的数据   read
写: 通过程序将数据写入文件中。 write
IO处理设备之间的数据传输。网络 磁盘

从流向进行划分: 输入流 /输出流

从操作内容上进行划分: 字节流 字符流

程序读取文件里面的数据:  read   输入流 InputStream
通过程序将数据写入文件中 write 输出流 OutputStream

==2.1 字节流==

计算机里面 所有文件内存存储 都是以字节的形式进行存储。 计算机里面全部都是二进制文件。

万能流。 可以操作计算机里面任意类型的文件。

1. 字节输入流 InputStream

public abstract class InputStream  extends Object implements Closeable
是一个物理资源 需要释放 finally

 

常用方法

abstract int read()  一次读取一个字节内容  -1  返回值: 读取到的字节内容

int read(byte[] b) 一次读取b.length个字节内容 读到的字节内容存储到字节数组里面
返回值: 有效字节个数 -1

int read(byte[] b, int off, int len) 一次读取b.length个字节内容
从off的索引位置 存储len个字节内容到字节数组中 返回值: 有效字节个数 -1

int available() ==> File.length() 获得文件内容大小

常用子类

 

 

FileInputStream

FileInputStream(File file) 
FileInputStream(String name)

 

read()

private static void testRead1() {

//读取指定文件数据----> 前提: 文件必须存在
String filePath = "day18/src/a.txt";
InputStream inputStream = null;
try {
//1.创建字节输入流对象--->打开了物理资源
inputStream = new FileInputStream(filePath);

//2. 循环读取文件数据 read
// int read = inputStream.read();
// while (read != -1) {
// System.out.print((char) read);
// read = inputStream.read();
// }

int len;
while ((len = inputStream.read()) != -1) {
System.out.print((char) len);
}

} catch (IOException e) {
e.printStackTrace();
} finally {
//释放物理资源
try {
if (inputStream != null) inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

 

try…with…resources

private static void testRead2() {
//jdk1.7+ 提供了一种更加优雅的方式释放资源 (自动释放资源) try...with....resources
try (
//创建流对象 前提: 类 implements Closeable
InputStream inputStream = new FileInputStream("day18/src/a.txt");
) {
//循环读取数据
int len;
while ((len = inputStream.read()) != -1) {
System.out.print((char) len);
}
} catch (IOException e) {
e.printStackTrace();
}

}

 

read(byte[] by)

 private static void testRead3() {

try (
InputStream inputStream = new FileInputStream("day18/src/a.txt")
) {

//读取资源
/* System.out.println(inputStream.available());
byte[] bytes = new byte[inputStream.available()];//length=1024的整数倍
int result = inputStream.read(bytes);//一次读取10个字节 result: 读取的有效的字节个数 -1
//想看数据 操作byte数组 字节数组转String
System.out.println(Arrays.toString(bytes));
//有效字节转String
System.out.println(new String(bytes,0,result));*/

int len;
byte[] bytes = new byte[1024];

while ((len = inputStream.read(bytes)) != -1) {
System.out.print(new String(bytes, 0, len));
}

} catch (IOException e) {
e.printStackTrace();
}

}

 

 

read(byte[] by, int off,int len)

 private static void testRead4() {
try (
InputStream inputStream = new FileInputStream("day18/src/a.txt")
) {

byte[] bytes = new byte[10];
int result = inputStream.read(bytes, 0, bytes.length);

System.out.println(Arrays.toString(bytes));
System.out.println(result);

} catch (IOException e) {
e.printStackTrace();
}
}

 

 

2. 字节输出流OutputStream

public abstract class OutputStream extends Object implements Closeable, Flushable

常用方法

abstract void write(int b)  
void write(byte[] b)
void write(byte[] b, int off, int len)

void close()
void flush()

常用子类

FileOutputStream(File file) 
FileOutputStream(File file, boolean append)
FileOutputStream(String name)
FileOutputStream(String name, boolean append)

 

 

write

public static void main(String[] args) {

//使用输出流: 文件不存在 自动的创建文件==> File.createNewFile()
try (
OutputStream outputStream = new FileOutputStream("day18/src/b.txt",false);
) {

//写入数据
//乱码: 编码格式不一致
outputStream.write("使用输出流".getBytes(Charset.forName("UTF-8")));
outputStream.write('\n');
outputStream.write("使用输出流".getBytes(),0,7);
outputStream.write(97);
outputStream.write('a');

outputStream.write("abc".getBytes());
outputStream.write('\n');
outputStream.write("abcd".getBytes(), 1, 2);

System.out.println("success");
} catch (IOException e) {
e.printStackTrace();
}
}

 

 

3. 模拟用户上传头像

文件上传和下载: 将一个地方文件放到另外一个地方 复制/粘贴

public class FileUtil {

private FileUtil() {
}


private static final String TARGET_DIRECTORY = "day18/upload/user/";
// day18/upload/user/2021-05-26/a.jpg
// day18/upload/user/2021-05-27/b.jpg
/**
* 文件上传
*
* @param sourceFilePath 源文件路径
*/
public static String fileUpload(String sourceFilePath) {

Objects.requireNonNull(sourceFilePath);
//读取源文件数据read--->InputStream 写入目标文件里面

//获得当前系统时间
String dateStr = LocalDate.now().toString();
File targetPath = new File(TARGET_DIRECTORY, dateStr);
if (!targetPath.exists()) {
targetPath.mkdirs();
}

//目标文件名称肯定与源文件名称一致
String fileName = sourceFilePath.substring(sourceFilePath.lastIndexOf(File.separator) + 1);
//保证文件名称唯一性 UUID
fileName = UUID.randomUUID().toString().replace("-", "") + "-" + fileName;

File targetFilePath = new File(targetPath, fileName);

try (
//1.创建流对象
InputStream inputStream = new FileInputStream(sourceFilePath);
OutputStream outputStream = new FileOutputStream(targetFilePath);
) {

//2. 循环读写
//小文件读写
/*int len;
while ((len = inputStream.read()) != -1) {
outputStream.write(len);
}*/

//大文件

//文件总量: 100byte
//读1个 写1个 100次

//byte[] by = new byte[20];
//读20个
//写5次
int len;
byte[] bytes = new byte[1024 * 20];//缓冲
while ((len = inputStream.read(bytes)) != -1) {
outputStream.write(bytes,0,len);
}
System.out.println("文件上传成功");
} catch (IOException e) {
e.printStackTrace();
}

return targetFilePath.getPath();
}


public static void main(String[] args) {
// System.out.println(fileUpload("C:\\Users\\DELL\\Pictures\\Saved Pictures\\a.jpg"));
// System.out.println(fileUpload("D:\\a.jpg"));
System.out.println(fileUpload("F:\\tools\\IDE\\idea\\ideaIU-2017.2.4.exe"));
// System.out.println(UUID.randomUUID().toString().replace("-", ""));
}
}

 

4. 高效字节流

BufferedInputStream: 高效的字节输入流 read

BufferedOutputStream 高效的字节输出流 write

普通的字节输入/输出流 FileInput/OutputStream 文件读写: 效率低的情况

为了提高程序读写的效率 基于装饰者设计模式 装饰了基本 字节输入/输出流的功能 提高了读写的效率。

高效原因: 底层自动提供了缓冲。 byte[] buf = new byte[8192];

BufferedInputStream(InputStream in) 
BufferedOutputStream(OutputStream out)
public static String fileUpload(String sourceFilePath) {

Objects.requireNonNull(sourceFilePath);
String dateStr = LocalDate.now().toString();
File targetPath = new File(TARGET_DIRECTORY, dateStr);
if (!targetPath.exists()) {
targetPath.mkdirs();
}

String fileName = sourceFilePath.substring(sourceFilePath.lastIndexOf(File.separator) + 1);
fileName = UUID.randomUUID().toString().replace("-", "") + "-" + fileName;

File targetFilePath = new File(targetPath, fileName);

try (
// InputStream inputStream = new FileInputStream(sourceFilePath);
// OutputStream outputStream = new FileOutputStream(targetFilePath);
BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(sourceFilePath));
BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(targetFilePath))
) {

byte[] bytes = new byte[1024*7];// <8192

int len;
while ((len = inputStream.read(bytes)) != -1) {
outputStream.write(bytes,0,len);
}
System.out.println("文件上传成功");
} catch (IOException e) {
e.printStackTrace();
}

return targetFilePath.getPath();
}

 

 

2.2 字符流

所有的文件全部是二进制的。 操作==文本文件==。 不能操作其它的二进制文件(压缩 视频 图片)

字节流+字符集

一个汉字: 2/3byte
文本文件:
纯文本文本: txt java html
有样式文本文件: doc xls ---->POI

 

Reader: read  字符输入流
Writer: write 字符输出流

 

1. 字符输入流 Reader

public abstract class Reader
extends Object
implements Readable, Closeable

 

常用方法

int read()  
int read(char[] cbuf)
abstract int read(char[] cbuf, int off, int len)

 

常用子类

 

FileReader

FileReader(File file) 
FileReader(String fileName)

 

read()

private static void demo1() {

//操作纯文本数据: txt java
//字符流操作文件内容: 永远也不会乱码
try (
//1.创建字符输入流对象(要求文件必须存在)
Reader reader = new FileReader("day19/src/demo.txt");
) {

//2. 调用read 循环读取文件内容

/* int len;
while ((len = reader.read()) != -1) {
System.out.print((char) len);
}*/

char[] chars = new char[1024 * 5];
int len;

while ((len = reader.read(chars)) != -1) {
//输出内容 字符数组转换String
System.out.print(new String(chars,0,len));
}
} catch (IOException e) {
e.printStackTrace();
}
}

 

 

 

 

 

2. 字符输出流 Writer

public abstract class Writer
extends Object
implements Appendable, Closeable, Flushable

 

常用子类

 

 

常用方法

void write(int c)  
void write(char[] cbuf)
void write(String str)
abstract void flush()
void write(String str, int off, int len)

 

FileWriter

FileWriter(String fileName) 
FileWriter(String fileName, boolean append)

FileWriter(File file, boolean append)
FileWriter(File file)
private static void demo1() {

try (
Writer writer = new FileWriter("day19/src/a.ini");
) {

//将数据存储文件中
writer.write('我');
writer.write(97);

writer.write("\n");
writer.write("abc".toCharArray());
writer.write("IO内容");

System.out.println("success");

} catch (IOException e) {
e.printStackTrace();
}
}

 

3. 文件复制

public static String fileUpload1(String filePath) {

try (
Reader reader = new FileReader(filePath);
Writer writer = new FileWriter(TARGET_DIRECTORY + "a.jpg");
) {

// int len;
// while ((len = reader.read()) != -1) {
// writer.write(len);
// }

char[] chars = new char[1024 * 5];
int len;
while ((len = reader.read(chars)) != -1) {
writer.write(chars, 0, len);
// writer.write(new String(chars,0,len));
}
} catch (IOException e) {
e.printStackTrace();
}

return null;
}

 

==4. 高效字符流==

装饰了基本字符流读写功能。 底层自带缓冲 8192 char[]

read—> FileReader

BufferedReader(Reader in) 
String readLine() 一次读取一行 读到末尾 null

 

模拟用户注册功能,持久化保存用户信息--->存储文件  id-name-pass-age
@SneakyThrows
private static void userReg() {

Scanner input = new Scanner(System.in);//获得用户在控制台录入的数据 read
String userInfoFilePath = "day19/src/userinfo.txt";


@Cleanup
Writer writer = new FileWriter(userInfoFilePath,true);
String answer;
do {
System.out.println("录入name:");
String name = input.next();
System.out.println("录入pass:");
String pass = input.next();
System.out.println("录入age:");
int age = input.nextInt();

//id-name-pass-age
String userInfo = String.join("-", idIndex + "", name, pass, age + "");
//用户注册的完整信息存储到文件里面 write---> OutPutStream Writer
writer.write(userInfo);
writer.write("\n");

System.out.println("是否继续y/n");
answer = input.next();
idIndex++;
} while ("y".equals(answer));

System.out.println("程序结束");

}

 

查询用户信息:
@SneakyThrows
private static List<UserInfo> selectAllUserInfo(String filePath) {
//read--->输入流--->字节输入流(字符输入流) InputStream Reader
List<UserInfo> userInfoList = new ArrayList<>(10);
//一次读取一行 BufferedReader
@Cleanup
BufferedReader reader = new BufferedReader(new FileReader(filePath));
//循环读取文件数据
String content;
while ((content = reader.readLine()) != null) {
//处理字符串数据
String[] array = content.split("-");
userInfoList.add(new UserInfo(Integer.parseInt(array[0]), array[1], array[2], Integer.parseInt(array[3])));
}
return userInfoList;
}

 

 

2.3 其它流

也是字节流或者是字符流的子类。

1. 数据流

属于字节流。 DataInputStream DataOutPutStream 操作字面量类型(基本+String)的数据。

DataInput/DataOutPut 前提: 必须先写

是否可以直接读取一个整数,或者一个小数?
字符流: readLine() ----> boolean 进行类型的转换

将一个用户完整的(属性)信息,写入文件中?
int id = 10001;//4byte
double dou = 100.123;//
boolean flag = true;

void writeUTF(String s); 网络数据传输(聊天)
String readUTF()

 

public class DataInputStream
extends FilterInputStream
implements DataInput

public class DataOutputStream
extends FilterOutputStream
implements DataOutput
 private static void demo2() {

try (
DataOutputStream dataOutputStream = new DataOutputStream(new FileOutputStream("day19/src/userinfo.txt"))
) {

int id = 1001;
double balance = 92736.876;
String name = "admin";
boolean flag = false;

dataOutputStream.writeInt(id);
dataOutputStream.writeDouble(balance);
dataOutputStream.writeUTF(name);
dataOutputStream.writeBoolean(flag);

System.out.println("success");

} catch (IOException e) {
e.printStackTrace();
}
}

 

 private static void demo1() {

try (
DataInputStream dataInput = new DataInputStream(new FileInputStream("day19/src/userinfo.txt"));
) {

int num = dataInput.readInt();//4
System.out.println(num);
double dou = dataInput.readDouble();
System.out.println(dou);

String str = dataInput.readUTF();
System.out.println(str);

boolean flag = dataInput.readBoolean();
System.out.println(flag);

//java.io.EOFException end of file
} catch (IOException e) {
e.printStackTrace();
}

}

 

==2. 序列化流==

也属于字节流。 对象流。增强了一个功能: 读写对象数据。

很多对象的信息也要进行设备间传输 保存磁盘文件。 必须先写在读

ObjectInputStream   DataInput  ObjectInput  read  反序列化
ObjectOutputStream writeObj 序列化流

 

解决方式: 实现Serializable

java.io.NotSerializableException: com.javasm.io_1.UserInfo
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
at com.javasm.io_2.ObjectStreamDemo.testWriteObj(ObjectStreamDemo.java:31)
at com.javasm.io_2.ObjectStreamDemo.main(ObjectStreamDemo.java:20)

 

流里面的class文件版本号和本地的class文件的版本号不一致、

解决方式: 1. 重新序列化 重新反序列化 不推荐

  1. 固定版本号id

java.io.InvalidClassException: com.javasm.io_1.UserInfo; local class incompatible: stream classdesc serialVersionUID = 8710310155550266680, local class serialVersionUID = 2985618370129842064
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:699)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1963)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1829)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2120)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1646)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:482)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:440)
at com.javasm.io_2.ObjectStreamDemo.testReadObj(ObjectStreamDemo.java:36)
at com.javasm.io_2.ObjectStreamDemo.main(ObjectStreamDemo.java:23)

 

 

 

 

3. 转换流

字符流子类。 字节流和字符流相互转换。

==字节流转字符流 (操作网络数据)==

OutputStreamWriter   

 

  1. 字节流转字符流 InputStreamRedear

抓取小说平台上的小说内容:
下载小说章节内容到 本地文件中。
InputStreamReader(InputStream in)
InputStreamReader(InputStream in, Charset cs)


private static void downloadNovel(String novelPath) {

//写入到本地磁盘: day19/novel/a.txt
//读写 字符流---> 高效字符流
//网络数据---> 字节流
// URL---> 统一资源定位符
//将字节输入流对象转换成成字符输入流对象
try (
BufferedReader reader = new BufferedReader(new InputStreamReader(new URL(novelPath).openStream()));//需要字符输入流对象
BufferedWriter writer = new BufferedWriter(new FileWriter("day19/novel/a.txt"))
) {

//循环读写
String line;
while ((line = reader.readLine()) != null) {
if(line.contains("<div class=\"read-content j_readContent\" id=\"\">")){
String novel = reader.readLine();
writer.write(novel.replaceAll("<p>","\n"));
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}

}

 

字符转字节

private static void demo() {
//读取文件内容 read 在控制台打印输出----> 写到控制台上 write
try (

BufferedReader reader = new BufferedReader(new FileReader("day19/novel/a.txt"));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));//写到控制台上
) {
String line;
while ((line = reader.readLine()) != null) {
writer.write(line);//字符流写转换成字节流写----> 字符流转字节流
writer.newLine();
}
} catch (IOException e) {
e.printStackTrace();
}

}

 

==4. Properties==

Properties是Map<K,V> 集合实现类。 属性集。 属性名称—>属性的值

public class PropUtil {

private PropUtil() {
}

private static final String PATH = "user.properties";
private static Properties properties;

static {
properties = new Properties();
try {
properties.load(PropUtil.class.getClassLoader().getResourceAsStream(PATH));
} catch (IOException e) {
e.printStackTrace();
}
}

public static String getValue(@NonNull String key) {
return properties.getProperty(key, "");
}
}
 

 

版权声明:本文为布耶尔原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/wang1999an/p/16861395.html