Java IO操作
1. 文件基本操作
public class IODemo1 {
public static void main(String[] args) throws IOException {
// File
File file = null;
// 创建
file = new File("E:/java/test.txt");
file.createNewFile();
// // 删除
// file.delete();
// // 重命名
// file.renameTo(new File("E:/java/test2.txt"));
// 检测
System.out.println("is or not exist " + file.exists());
System.out.println("is or not file " + file.isFile());
System.out.println("is or not read " + file.canRead());
System.out.println("is or not write " + file.canWrite());
System.out.println("absolute " + file.isAbsolute());
// 访问
System.out.println("name " + file.getName());
System.out.println("name " + file.getPath());
System.out.println("name " + file.getAbsolutePath());
System.out.println("name " + file.getParent());
System.out.println("name " + file.length());
System.out.println("name " + file.lastModified());
// 目录操作
file = new File("E:/java/testRoute");
file.mkdir();
System.out.println(Arrays.toString(file.listFiles())); // 当前目录下的所有文件
System.out.println(Arrays.toString(file.getParentFile().listFiles())); // 上级目录下的所有文件
// 删除 改名 判断 访问方法对目录也适用
// 相对路径
file = new File("abc.txt"); // 相对路径为相对于项目的位置
file.createNewFile();
System.out.println("name " + file.getPath());
System.out.println("name " + file.getAbsolutePath() );
System.out.println("name " + file.getParent());
// 相对路径下获取上级目录
System.out.println("上级目录" + file.getAbsoluteFile().getParent());
}
}
2. 过滤文件
public class IODemo2 {
// 过滤文件
public static void main(String[] args) {
File dir = new File("E:\\JavaCode\\java\\filetest");
File[] files = dir.listFiles();
files = dir.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
// System.out.println(pathname);
if (pathname.getName().endsWith((".txt"))) {
return true;
}
return false;
}
});
files = dir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
// System.out.println(dir.getName() + "," + name);
if (name.endsWith(".txt")) {
return true;
}
return false;
}
});
System.out.println(Arrays.toString(files));
}
}
3. 遍历文件
public class IODemo3 {
// 遍历文件
public static void main(String[] args) {
printFile("E:\\java\\src\\com\\nowcoder", 0);
}
/*
* alpha 子目录中有文件 则缩进
* a
* - x.png
* - y.png
* - 1.txt
* - 2.txt
* */
public static void printFile(String filePath, int depth) { // depth为目录深度
File file = new File(filePath);
if (!file.exists()) {
throw new IllegalArgumentException("文件不存在");
}
// 打印空格
for (int i = 0; i < depth; i++) {
System.out.print(" ");
}
// 打印名字
if (file.isFile()) {
System.out.print(" - ");
}
System.out.println(file.getName());
// 目录递归
if (file.isDirectory()) {
File[] files = file.listFiles();
for (File f : files) {
printFile(f.getPath(), depth + 1);
}
}
}
}
4. 复制文件(字节流、字符流)
public class IODemo4 {
// 文件流
public static void main(String[] args) {
// copyFile("E:\\java\\1.jpg","E:\\java\\2.jpg");
// copyFile("E:\\java\\test1.txt","E:\\java\\txt2.txt");
copyTxtFile("E:\\java\\test1.txt","E:\\java\\txt2.txt");
}
// 字节流
public static void copyFile(String srcFilePath, String destFilePath) {
try (
FileInputStream fis = new FileInputStream(srcFilePath);
FileOutputStream fos = new FileOutputStream(destFilePath);
) {
byte[] bytes = new byte[128];
int len = 0; // 实际读取的字节数
while ((len = fis.read(bytes, 0,128)) > 0) { // 最多读128
fos.write(bytes,0,len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void copyTxtFile(String srcFilePath, String destFilePath) {
try (
FileReader fr = new FileReader(srcFilePath);
FileWriter fw = new FileWriter(destFilePath);
){
char[] chars = new char[128];
int len = 0; // 实际读的字符数
while ((len = fr.read(chars, 0,128)) > 0) {
System.out.println(String.valueOf(chars,0,len)); // 将数组按照字符串形式打印出来
fw.write(chars,0,len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
4.1 字符流与字节流相关知识
- InputStream、OutputStream
处理字节流的抽象类
InputStream 是字节输入流的所有类的超类,一般我们使用它的子类,如FileInputStream等.
OutputStream是字节输出流的所有类的超类,一般我们使用它的子类,如FileOutputStream等.
- InputStreamReader OutputStreamWriter
为了实现字节到字符的有效转换,可以从基础流中提取比满足当前读取操作所需的更多字节。为了获得最高效率,请考虑在BufferedReader中包装InputStreamReader
InputStreamReader 是字节流通向字符流的桥梁,它将字节流转换为字符流.
OutputStreamWriter是字符流通向字节流的桥梁,它将字符流转换为字节流.
- BufferedReader BufferedWriter
BufferedReader 由Reader类扩展而来,提供通用的缓冲方式文本读取,readLine读取一个文本行,
从字符输入流中读取文本,缓冲各个字符,从而提供字符、数组和行的高效读取。
BufferedWriter 由Writer 类扩展而来,提供通用的缓冲方式文本写入, newLine使用平台自己的行分隔符,
将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
BufferedReader readWb = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.in : 从键盘输入的字节流
socket.getInputStream(): 端口输入字节流
InputStreamReader : 将字节流转换为字符流
BufferedReader:从字符输入流中读取文本,缓冲各个字符
- 字节流与字符流区别
字节流在操作时本身不会用到缓冲区(内存),是文件本身直接操作的,而字符流在操作时使用了缓冲区,通过缓冲区再操作文件
4.2 缓冲区
缓冲区可以简单地理解为一段内存区域。
可以简单地把缓冲区理解为一段特殊的内存。
某些情况下,如果一个程序频繁地操作一个资源(如文件或数据库),则性能会很低,此时为了提升性能,就可以将一部分数据暂时读入到内存的一块区域之中,以后直接从此区域中读取数据即可,因为读取内存速度会比较快,这样可以提升程序的性能。
在字符流的操作中,所有的字符都是在内存中形成的,在输出前会将所有的内容暂时保存在内存之中,所以使用了缓冲区暂存数据。
如果想在不关闭时也可以将字符流的内容全部输出,则可以使用Writer类中的flush()方法完成。
5. 复制文件(缓冲流)
public class IODemo5 {
// 缓冲流
public static void main(String[] args) {
copyFile("E:\\java\\2.jpg","E:\\java\\3.jpg");
}
public static void copyFile(String srcFilePath,String destFilePath) {
try (
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFilePath)); // 缓冲流接入节点流
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFilePath));
) {
// 使用字节流读取文件
byte[] bytes = new byte[128];
int len = 0;
while ((len = bis.read(bytes,0,128)) > 0) {
bos.write(bytes,0,len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
6. 打印流
public class IODemo7 {
// 打印流
public static void main(String[] args) {
// testPrintStream();
testPrintWriter();
}
public static void testPrintStream() {
try (
FileOutputStream fos = new FileOutputStream("E:\\java\\output.txt");
PrintStream ps = new PrintStream(fos);
){
ps.println("112");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void testPrintWriter() {
try (
FileWriter fw = new FileWriter("E:\\java\\output2.txt");
PrintWriter pw = new PrintWriter(fw);
){
pw.println("11111");
} catch (IOException e) {
e.printStackTrace();
}
}
}
7. 访问文件多个位置(如:追加)
public class IODemo8 {
// RAF 可以自由访问文件多个位置 如追加
public static void main(String[] args) {
try (
RandomAccessFile raf = new RandomAccessFile("E:\\java\\output.txt","rw");
){
// 定位至文件末尾
raf.seek(raf.length());
raf.write("test input data".getBytes()); // 将字节写入
// 指针定位到开头
raf.seek(0);
String line = null;
while ((line = raf.readLine()) != null) {
// String -> bytes (二进制) (UTF-8)
// bytes -> String (ISO8859-1) (解码)
// String -> bytes (ISO8859-1) 将乱码字符串解码为字节
// bytes -> String (UTF-8) 将字节以utf-8形式转为字符串
byte[] bytes = line.getBytes("ISO8859-1");
line = new String(bytes,"UTF-8");
System.out.println(line);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}