Этот пост пытается охватить полный набор операций в java.io. По сравнению с другими книгами и блогами, связанными с этой темой, моя мотивация состоит в том, чтобы показывать практические рекомендации с помощью тематических исследований. Будучи студентом Java, я понимаю, что наиболее эффективный способ изучения нового языка программы — это примеры: скопируйте и вставьте фрагмент кода, запустите его, чтобы увидеть результаты, затем попытайтесь изменить и повторно запустить его пошагово , Поэтому я предполагаю, что этот пост будет полезным.
Стоит отметить, что этот пост не будет касаться ничего, связанного с java.nio, потому что я думаю, что это совсем другая тема.
Содержание
- Случай 0: создать новый файл
- Случай 1: две константы в файле
- Случай 2: Удалить файл
- Случай 3: Создать каталог
- Случай 4: список файлов и каталогов в данном каталоге
- Случай 5: проверяет, является ли файл файлом
- Случай 6: запись в файл RandomAccessFile
- Случай 7: запись байтов в файл
- Случай 8: добавление байтов в файл
- Случай 9: чтение байтов из файла
- Случай 10: Копировать файлы
- Случай 11: запись символов в файл
- Случай 12: чтение символов из файла
- Случай 13: преобразование из OutputStream в FileWriter
- Случай 14: Преобразование из InputStream в FileReader
- Случай 15: использование конвейера
- Случай 16: записать отформатированную строку в файл
- Случай 17: перенаправить «стандартный» ввод-вывод
- Случай 18: чтение файла построчно
- Случай 19: Сжать в ZIP-файл
- Случай 20: выписка из архива
- Случай 21: отодвинуть байты назад
Случай 0: создать новый файл
|
01
02
03
04
05
06
07
08
09
10
11
|
import java.io.File;public class FileOperationTest { public static void main(String[] args) { File f = new File("helloworld.txt"); try { f.createNewFile(); } catch (Exception e) { e.printStackTrace(); } }} |
Вывод: новый и пустой файл создается в рабочем каталоге, если до этого не было helloword.txt.
Случай 1: две константы в файле
|
1
2
3
4
5
6
7
|
import java.io.File;public class FileOperationTest { public static void main(String[] args) { System.out.println(File.separator); System.out.println(File.pathSeparator); }} |
Выход:
|
1
2
|
/: |
Я получаю вывод выше, потому что я работаю на Linux. Если вы используете Windows, вывод должен быть \ и ; , Как можно видеть, с целью переносимости и надежности всегда рекомендуется использовать эти две константы.
Случай 2: Удалить файл
|
01
02
03
04
05
06
07
08
09
10
11
12
13
|
import java.io.File;public class FileOperationTest { public static void main(String[] args) { File f = new File("helloworld.txt"); if (f.exists()) { if (!f.delete()) { System.out.println("the file cannot be deleted."); } } else { System.out.println("the file does not exist."); } }} |
Случай 3: Создать каталог
|
1
2
3
4
5
6
7
|
import java.io.File;public class FileOperationTest { public static void main(String[] args) { File f = new File("hello"); f.mkdir(); }} |
Случай 4: список файлов и каталогов в данном каталоге
|
1
2
3
4
5
6
7
8
9
|
import java.io.File;public class FileOperationTest { public static void main(String[] args) { File f = new File("."); for (String str : f.list()) { System.out.println(str); } }} |
Вывод: я использую Eclipse
|
1
2
3
4
5
|
.settings.classpath.projectsrcbin |
Файл list () возвращает массив строк. Если вы предпочитаете массив File s, пожалуйста, используйте File . listFiles () :
|
1
2
3
4
5
6
7
8
9
|
import java.io.File;public class FileOperationTest { public static void main(String[] args) { File f = new File("."); for (File subFile : f.listFiles()) { System.out.println(subFile.getName()); } }} |
Случай 5: проверяет, является ли файл файлом
|
01
02
03
04
05
06
07
08
09
10
11
|
import java.io.File;public class FileOperationTest { public static void main(String[] args) { File f = new File("helloworld.txt"); if (f.isFile()) { System.out.println("YES"); } else { System.out.println("NO"); } }} |
В сочетании с файлом . listFiles () , мы можем перечислить все файлы в данном каталоге и его подкаталогах.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
import java.io.File;public class FileOperationTest { public static void main(String[] args) { File f = new File("."); listFiles(f); } private static void listFiles(File f) { if (f.isFile()) { System.out.println(f.getName()); return; } for (File subFile : f.listFiles()) { listFiles(subFile); } }} |
Выход: по сравнению с делом 4, чтобы увидеть разницу
|
1
2
3
4
5
|
org.eclipse.jdt.core.prefs.classpath.projectFileOperationTest.javaFileOperationTest.class |
Случай 6: запись в файл RandomAccessFile
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
import java.io.IOException;import java.io.RandomAccessFile;public class FileOperationTest { public static void main(String[] args) throws IOException { RandomAccessFile file = new RandomAccessFile( "helloworld.txt", "rw"); file.writeBytes("hello world!"); file.writeChar('A'); file.writeInt(1); file.writeBoolean(true); file.writeFloat(1.0f); file.writeDouble(1.0); file.close(); }} |
Если вы откроете файл с помощью текстового редактора, вы найдете искаженный код, кроме первого « hello world!A (Обратите внимание на символ « A в конце «Привет, мир!»). Это связано с тем, что RandomAccessFile записывает в файл только массив байтов.
Случай 7: запись байтов в файл
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
import java.io.FileOutputStream;import java.io.IOException;import java.io.OutputStream;public class FileOperationTest { public static void main(String[] args) throws IOException { OutputStream out = new FileOutputStream( "helloworld.txt"); String str = "hello world!"; out.write(str.getBytes()); out.close(); }} |
На этот раз вы можете увидеть «Привет, мир!» в файле. Конечно, вы можете записывать в байты OutputStream побайтно, но это менее эффективно:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
import java.io.FileOutputStream;import java.io.IOException;import java.io.OutputStream;public class FileOperationTest { public static void main(String[] args) throws IOException { OutputStream out = new FileOutputStream( "helloworld.txt"); String str = "hello world!"; for (byte b : str.getBytes()) { out.write(b); } out.close(); }} |
Случай 8: добавление байтов в файл
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
import java.io.FileOutputStream;import java.io.IOException;import java.io.OutputStream;public class FileOperationTest { public static void main(String[] args) throws IOException { OutputStream out = new FileOutputStream( "helloworld.txt", true); String str = "hello world!"; out.write(str.getBytes()); out.close(); }} |
Вывод: hello world!hello world!
Случай 9: чтение байтов из файла
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;public class FileOperationTest { public static void main(String[] args) throws IOException { InputStream in = new FileInputStream("helloworld.txt"); byte[] bs = new byte[1024]; int len = -1; while ((len = in.read(bs)) != -1) { System.out.println(new String(bs, 0, len)); } in.close(); }} |
InputStream . read () вернет -1, если достигнет конца файла. В противном случае он вернет общее количество байтов, считанных в буфер.
Случай 10: Копировать файлы
Просто объедините Case 7 и 9 , мы получим функцию копирования.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;public class Copy { public static void main(String[] args) throws IOException { if (args.length != 2) { System.out.println("java Copy SOURCE DEST"); System.exit(1); } InputStream input = new FileInputStream(args[0]); OutputStream output = new FileOutputStream(args[1]); int len = 0; byte bs[] = new byte[1024]; while ((len = input.read(bs)) != -1) { output.write(bs, 0, len); } input.close(); output.close(); }} |
Случай 11: запись символов в файл
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
import java.io.FileWriter;import java.io.IOException;import java.io.Writer;public class FileOperationTest { public static void main(String[] args) throws IOException { Writer out = new FileWriter("helloworld.txt"); String str = "hello world!"; out.write(str); out.close(); }} |
В приведенном выше случае вы получите тот же результат, что и в случае 7 . Так в чем же разница? FileWriter предназначен для написания потоков символов. Он будет использовать кодировку символов по умолчанию и размер байтового буфера по умолчанию. Другими словами, для удобства это класс-оболочка FileOutputStream . Поэтому, чтобы указать эти значения самостоятельно, рассмотрите возможность использования FileOutputStream .
Случай 12: чтение символов из файла
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
import java.io.FileReader;import java.io.IOException;import java.io.Reader;public class FileOperationTest { public static void main(String[] args) throws IOException { Reader in = new FileReader("helloworld.txt"); char cs[] = new char[1024]; int len = -1; while ((len = in.read(cs)) != -1) { System.out.println(new String(cs, 0, len)); } in.close(); }} |
Использовать ли потоки байтов или символов? Это действительно зависит. У обоих есть буферы. InputStream / OutputStream обеспечивают большую гибкость, но сделают вашу «простую» программу сложной. С другой стороны, FileWriter / FileReader дают удобное решение, но вы теряете контроль.
Случай 13: преобразование из OutputStream в FileWriter
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
import java.io.FileOutputStream;import java.io.IOException;import java.io.OutputStreamWriter;import java.io.Writer;public class FileOperationTest { public static void main(String[] args) throws IOException { Writer out = new OutputStreamWriter( new FileOutputStream("helloworld.txt")); out.write("hello world!"); out.close(); }} |
Вместо использования кодировки символов по умолчанию вы можете указать кодировку. Например,
|
1
2
|
Writer out = new OutputStreamWriter( new FileOutputStream("helloworld.txt"), "utf8"); |
Случай 14: Преобразование из InputStream в FileReader
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
import java.io.FileInputStream;import java.io.IOException;import java.io.InputStreamReader;import java.io.Reader;public class FileOperationTest { public static void main(String[] args) throws IOException { Reader in = new InputStreamReader( new FileInputStream("helloworld.txt")); char cs[] = new char[1024]; int len = -1; while ((len = in.read(cs)) != -1) { System.out.println(new String(cs, 0, len)); } in.close(); }} |
Случай 15: использование конвейера
Следующий код создает два потока: источник, который записывает что-то в конвейер на одном конце, и потребитель, который считывает это из конвейера на другом конце. Чтобы создать конвейер, нам нужно создать PipedInputStream и PipedOutputStream отдельно и соединить их с помощью output.connect(input) или через их конструкторы. В этой программе я намеренно запускаю поток Consumer сначала и прошу всю программу поспать 1 секунду перед запуском потока Producer. Это покажет, что конвейер работает. Стоит отметить, что я закрываю конвейер в источнике, потому что « поток, который пишет в поток, должен всегда закрывать OutputStream перед завершением. «Если мы удалим out.close() , будет out.close() IOException
|
1
2
3
4
5
6
|
java.io.IOException: Write end dead at java.io.PipedInputStream.read(PipedInputStream.java:311) at java.io.PipedInputStream.read(PipedInputStream.java:378) at java.io.InputStream.read(InputStream.java:101) at foo.Consumer.run(FileOperationTest.java:58) at java.lang.Thread.run(Thread.java:701) |
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.io.PipedInputStream;import java.io.PipedOutputStream;public class FileOperationTest { public static void main(String[] args) throws IOException, InterruptedException { PipedInputStream input = new PipedInputStream(); PipedOutputStream output = new PipedOutputStream(); output.connect(input); Producer producer = new Producer(output); Consumer consumer = new Consumer(input); new Thread(consumer).start(); Thread.sleep(1000); new Thread(producer).start(); }}class Producer implements Runnable { private final OutputStream out; public Producer(OutputStream out) { this.out = out; } @Override public void run() { String str = "hello world!"; try { out.write(str.getBytes()); out.flush(); out.close(); } catch (Exception e) { e.printStackTrace(); } }}class Consumer implements Runnable { private final InputStream in; public Consumer(InputStream in) { this.in = in; } @Override public void run() { byte[] bs = new byte[1024]; int len = -1; try { while ((len = in.read(bs)) != -1) { System.out.println(new String(bs, 0, len)); } } catch (IOException e) { e.printStackTrace(); } }} |
Случай 16: записать отформатированную строку в файл
PrintStream добавляет функциональность для удобной печати представлений различных значений данных. Синтаксис строки формата почти такой же, как C.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
import java.io.FileOutputStream;import java.io.IOException;import java.io.PrintStream;public class FileOperationTest { public static void main(String[] args) throws IOException { PrintStream print = new PrintStream( new FileOutputStream("helloworld.txt")); print.printf("%s %s!", "hello", "world"); print.close(); }} |
Случай 17: перенаправить «стандартный» ввод-вывод
В Java и стандартный вывод, и вывод ошибок — PrintStream s. Стандартный ввод — InputStream . Поэтому мы можем переназначить их свободно. Следующий код перенаправляет стандартный вывод на вывод ошибок.
|
1
2
3
4
5
6
7
|
public class FileOperationTest { public static void main(String[] args) { System.out.println("hello world!"); System.setOut(System.err); System.out.println("hello world!"); }} |
Вывод: в Eclipse красный текст означает сообщение об ошибке
|
1
|
hello world!hello world! |
Случай 18: чтение файла построчно
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
import java.io.BufferedReader;import java.io.FileReader;import java.io.IOException;public class FileOperationTest { public static void main(String[] args) throws IOException { BufferedReader reader = new BufferedReader( new FileReader("helloworld.txt")); String str = null; while ((str = reader.readLine()) != null) { System.out.println(str); } reader.close(); }} |
Случай 19: Сжать в ZIP-файл
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
import java.io.FileOutputStream;import java.io.IOException;import java.util.zip.ZipEntry;import java.util.zip.ZipOutputStream;public class FileOperationTest { public static void main(String[] args) throws IOException { ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream( "helloworld.zip")); String str = "hello world!"; for (int i = 0; i < 3; i++) { zipOut.putNextEntry(new ZipEntry("helloworld" + i + ".txt")); zipOut.write(str.getBytes()); zipOut.closeEntry(); } zipOut.close(); }} |
Приведенный выше код создает zip-файл и помещает три файла с именами «helloworld0.txt», «helloworld1.txt» и «helloworld2.txt», каждый из которых содержит контент «hello world!».
Случай 20: выписка из архива
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
import java.io.FileInputStream;import java.io.IOException;import java.util.zip.ZipEntry;import java.util.zip.ZipInputStream;public class FileOperationTest { public static void main(String[] args) throws IOException { ZipInputStream zipIn = new ZipInputStream(new FileInputStream( "helloworld.zip")); ZipEntry entry = null; byte bs[] = new byte[1024]; while ((entry = zipIn.getNextEntry()) != null) { // get file name System.out.printf("file: %s content: ", entry.getName()); int len = -1; // read current entry to the buffer while((len=zipIn.read(bs)) != -1) { System.out.print(new String(bs, 0, len)); } System.out.println(); } zipIn.close(); }} |
Выход:
|
1
2
3
|
file: helloworld0.txt content: hello world!file: helloworld1.txt content: hello world!file: helloworld2.txt content: hello world! |
Случай 21: отодвинуть байты назад
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
import java.io.ByteArrayInputStream;import java.io.IOException;import java.io.PushbackInputStream;public class FileOperationTest { public static void main(String[] args) throws IOException { PushbackInputStream push = new PushbackInputStream( new ByteArrayInputStream("hello, world!".getBytes())); int temp = 0; while ((temp = push.read()) != -1) { if (temp == ',') { push.unread('.'); } System.out.print((char) temp); } }} |
Приведенный выше код ставит точку после чтения запятой, поэтому вывод
|
1
|
hello,. world! |
Однако, если вы попытаетесь отодвинуть больше символов назад, например push.unread("(...)".getBytes()); , вы получите IOException : Push Back буфер заполнен. Это связано с тем, что по умолчанию размер буфера pushback равен 1. Чтобы указать его с большей емкостью, используйте конструктор PushbackInputStream(InputStream in, int size) , например
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
import java.io.ByteArrayInputStream;import java.io.IOException;import java.io.PushbackInputStream;public class FileOperationTest { public static void main(String[] args) throws IOException { PushbackInputStream push = new PushbackInputStream( new ByteArrayInputStream("hello, world!".getBytes()), 10); int temp = 0; while ((temp = push.read()) != -1) { if (temp == ',') { push.unread("(...)".getBytes()); } System.out.print((char) temp); } }} |
Выход:
|
1
|
hello,(...) world! |