основное содержание
1. Проблемы с кодированием
2. Использование класса File
3. Использование RandomAccessFile
4. Входные и выходные потоки ввода/вывода
Проблемы с кодировкой:
1 import java.io.UnsupportedEncodingException;
2
3 public class 编码问题 {
4 public static void main(String[] args) {
5 // 我们项目的默认编码是GBK
6 String s = "测试 ABC";
7 byte[] byte1 = s.getBytes();// 转换成的字节序列用的是项目默认的编码gbk
8 for (byte b : byte1) {
9 // 1 byte = 8 位 //toHexString这个函数是把字节(转换成了Int)以16进制的方式显示
10 System.out.print(Integer.toHexString(b & 0xff) + " ");// &
11 // 0xff是为了把前面的24个0去掉只留下后八位
12 }
13
14 try {
15 // 也可以转换成指定的编码
16 byte[] bytes1 = s.getBytes("gbk");
17 System.out.println(new String(bytes1));
18 } catch (UnsupportedEncodingException e) {
19 // TODO Auto-generated catch block
20 e.printStackTrace();
21 }
22 /**
23 * gbk编码: 中文占用两个字节,英文占用一个字节 utf-8编码:中文占用三个字节,英文占用一个字节
24 * java是双字节编码,是utf-16be编码 utf-16be编码:中文占用两个字节,英文占用两个字节
25 * 当你的字节序列是某种编码时,这个时候想把字节序列变成字符串,也需要用这种编码方式,否则会出现乱码
26 */
27 try {
28 byte[] byte2 = s.getBytes("utf-16be");
29 String s2 = new String(byte2, "utf-16be");
30 System.out.println(s2);
31 } catch (UnsupportedEncodingException e) {
32 // TODO Auto-generated catch block
33 e.printStackTrace();
34 }
35 /**
36 * 文本文件就是字节序列,可以是任意编码的字节序列
37 * 如果我们在中文机器上直接创建文本文件,那么该文件只认识ANSI编码(例如直接在电脑中创建文本文件)
38 */
39
40 /**
41 * byte转int的时候为什么非要先&0xff计算出来才是正确答案?
42 * 首先,java中的二进制采用的是补码形式,并非原码或反码,这3个概念要搞清楚;
43 * 其次,byte占8位,int占32位,将byte强制转换为int型时,如果没有做 &
44 * 0xff运算,且byte对应的值为负数的话,就会对高位3个字节进行补位,这样就有可能出现补位误差的错误。
45 * 举例来说,byte型的-1,其二进制(补码)为11111111(即0xff),转换成int型,值也应该为-1,但经过补位后,
46 * 得到的二进制为11111111111111111111111111111111(即0xffffffff),这就不是-1了,对吧?
47 * 而0xff默认是int型,所以,一个byte跟0xff相与,会先将那个byte转化成int型运算,这样,结果中的高位3个字节就总会被清0,
48 * 于是结果就是我们想要的了~
49 */
50
51 }
52
53 }
View Code
Использование класса File:
Класс JAVA.io.File используется для представления файла (каталога). Класс File используется только для представления информации (имя, размер и т. д.) файла (каталога) и не может использоваться для доступа к содержимому файла. API класса File: 1. Создайте объект File: File file=new File(String path); Примечание: File.seperator(); Получите системный разделитель, например: "\". 2.boolean file.exists( ); существует ли он. 3.file.mkdir(); или file.mkdirs(); создать каталог или многоуровневый каталог. 4.file.isDirectory() или file.isFile(), чтобы определить, является ли это каталогом или файлом. 5.file.delete();удалить файл или каталог. 6.file.createNewFile(); Создать новый файл. 7.file.getName() Получить имя файла или абсолютный путь к каталогу. 8.file.getAbsolutePath() получает абсолютный путь. 9.file.getParent(); Получить абсолютный путь к родителю. 10.file.getSize(); Получить размер файла. 11.file.getFormat(); Получить имя формата файла. 1 import java.io.File;
2 import java.io.IOException;
3
4 public class FileDemo {
5
6 /**
7 * @param args
8 */
9 public static void main(String[] args) {
10 // 了解构造函数的情况 查帮助ALT+/
11 File file = new File("E:\\javaio\\imooc");
12 // 判断文件/文件夹是否存在
13 // System.out.println(file.exists());
14 if (!file.exists())
15 file.mkdir(); // file.mkdirs()如果文件不存在,直接创建文件夹
16 // mkdir创建的一级目录,如果需要创建多级目录可以使用mkdirs()
17 else
18 file.delete();
19
20 // 是否是一个目录 如果是目录返回true,如果不是目录or目录不存在返回的是false
21 System.out.println(file.isDirectory());
22 // 是否是一个文件
23 System.out.println(file.isFile());
24
25 // File file2 = new File("e:\\javaio\\日记1.txt");
26 File file2 = new File("e:\\javaio", "日记1.txt");
27 if (!file2.exists())
28 try {
29 file2.createNewFile();
30 } catch (IOException e) {
31 // TODO Auto-generated catch block
32 e.printStackTrace();
33 }
34 else
35 file2.delete();
36 // 常用的File对象的API
37 System.out.println(file);// file.toString()的内容
38 System.out.println(file.getAbsolutePath());
39 System.out.println(file.getName());
40 System.out.println(file2.getName());
41 System.out.println(file.getParent());
42 System.out.println(file2.getParent());
43 System.out.println(file.getParentFile().getAbsolutePath());
44 }
45
46 }
FileDemo
обход каталога
1 import java.io.File;
2 import java.io.IOException;
3
4 //列出File的一些常用操作比如过滤,遍历等操作
5 public class FileUtils {
6 /**
7 * 列出指定指定目录下(包括其子目录)的所有文件
8 *
9 * @param dir
10 * @throws IOException
11 */
12 public static void listDirectory(File dir) throws IOException {
13 if (!dir.exists()) {
14 throw new IllegalArgumentException("目录:" + dir + "不存在");
15 }
16 if (!dir.isDirectory()) {
17 throw new IllegalArgumentException(dir + "不是目录");
18 }
19
20 // String[] fileNames =
21 // dir.list();//返回的是字符串数组,list()方法用于列出当前目录下的子目录和文件,直接子的名称,不包含子目录下的内容
22 // for (String string : fileNames) {
23 // System.out.println(dir+"\\"+string);
24 // }
25 //
26 // 如果要遍历子目录下的内容就需要构造成File对象做递归操作,File提供了直接返回File对象的API
27 File[] files = dir.listFiles();// 返回的是直接子目录(文件)的抽象
28 if (files != null && files.length > 0) {// 确定存在子目录
29 for (File file : files) {
30 if (file.isDirectory()) {
31 // 递归
32 listDirectory(file);
33 } else {
34 System.out.println(file);
35 }
36 }
37 }
38 }
39 }
FileUtils
Использование RandomAccessFile
RandomAccessFile JAVA обеспечивает доступ к содержимому файла, который может как читать, так и записывать файлы. RandomAccessFile поддерживает произвольный доступ к файлам и может получить доступ к любому местоположению файла (1) файлы файловой модели JAVA на жестком диске хранятся в формате байт байт байт, который представляет собой набор данных (2) существует два режима открытия файлов "rw " (чтение и запись) "r" (только чтение) RandomAccessFile raf = новый указатель файла RandomeAccessFile(file,"rw"), указатель в начале при открытии файла указатель = 0;(3) записать метод raf.write(int) --->записать только один байт (последние 8 бит), в то же время указатель указывает на следующую позицию, готов к повторной записи, чтобы обеспечить и множество методов может читать и записывать по одному Основные типы данных (4) метод чтения int b = raf.read() ---> чтение одного байта (5) должен быть закрыт после чтения и записи файла (официальные инструкции Oracle) 1 import java.io.File;
2 import java.io.IOException;
3 import java.io.RandomAccessFile;
4 import java.util.Arrays;
5
6 public class RafDemo {
7
8 /**
9 * @param args
10 */
11 public static void main(String[] args) throws IOException {
12 File demo = new File("demo");
13 if (!demo.exists())
14 demo.mkdir();
15 File file = new File(demo, "raf.dat");
16 if (!file.exists())
17 file.createNewFile();
18
19 RandomAccessFile raf = new RandomAccessFile(file, "rw");
20 // 指针的位置
21 System.out.println(raf.getFilePointer());
22
23 raf.write('A');// 只写了一个字节
24 System.out.println(raf.getFilePointer());
25 raf.write('B');
26
27 int i = 0x7fffffff;
28 // 用write方法每次只能写一个字节,如果要把i写进去就得写4次
29 raf.write(i >>> 24);// 高8位
30 raf.write(i >>> 16);
31 raf.write(i >>> 8);
32 raf.write(i);
33 System.out.println(raf.getFilePointer());
34
35 // 可以直接写一个int
36 raf.writeInt(i);
37
38 String s = "中";
39 byte[] gbk = s.getBytes("gbk");
40 raf.write(gbk);
41 System.out.println(raf.length());
42
43 // 读文件,必须把指针移到头部
44 raf.seek(0);
45 // 一次性读取,把文件中的内容都读到字节数组中
46 byte[] buf = new byte[(int) raf.length()];
47 raf.read(buf);
48
49 System.out.println(Arrays.toString(buf));
50 for (byte b : buf) {
51 System.out.println(Integer.toHexString(b & 0xff) + " ");
52 }
53 raf.close();
54 }
55
56 }
RafDemo
import java.io.IOException;
import java.io.RandomAccessFile;
public class RafReadDemo {
/**
* @param args
*/
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
RandomAccessFile raf = new RandomAccessFile("demo/raf.dat", "r");
raf.seek(2);
int i = 0;
int b = raf.read();// 读取到一个字节
System.out.println(raf.getFilePointer());
i = i | (b << 24);
b = raf.read();
i = i | (b << 16);
b = raf.read();
i = i | (b << 8);
b = raf.read();
i = i | b;
System.out.println(Integer.toHexString(i));
raf.seek(2);
i = raf.readInt();
System.out.println(Integer.toHexString(i));
raf.close();
}
}
Сериализация RafReadDemo и базовая сериализация типов 1) Процесс преобразования типа int в байт или преобразования других типов данных в байты называется сериализацией данных---->n байт 2) Десериализация преобразует n байтов в одни данные Процесс nbyte --- > данные 3) RandomAccessFile предоставляет основные типы методов чтения и записи, которые могут сериализовать данные базового типа в файлы или десериализовать содержимое файла в данные
1 import java.io.File;
2 import java.io.IOException;
3 import java.io.RandomAccessFile;
4 public class RandomAccessFileSeriaDemo {
5
6 /**
7 * @param args
8 */
9 public static void main(String[] args) throws IOException {
10 // TODO Auto-generated method stub
11 File demo = new File("demo1");
12 if (!demo.exists())
13 demo.mkdir();
14 File file = new File(demo, "raf.dat");
15 if (!file.exists())
16 file.createNewFile();
17 // 打开文件,进行随机读写
18 RandomAccessFile raf = new RandomAccessFile(file, "rw");
19 /* 序列化 */
20 int i = 0x7ffffff;
21 raf.write(i >>> 24);
22 raf.write(i >>> 16);
23 raf.write(i >>> 8);
24 raf.write(i);
25 System.out.println(raf.getFilePointer());
26
27 /* 反序列化 */
28 raf.seek(0);
29 int b = raf.read();
30 i = i | (b << 24);
31 b = raf.read();
32 i = i | (b << 16);
33 b = raf.read();
34 i = i | (b << 8);
35 b = raf.read();
36 i = i | b;
37 System.out.println(Integer.toHexString(i));
38 raf.close();
39 }
40 }
41
42 RandomAccessFileSeriaDemo
RandomAccessFileSeriaDemo
Входные и выходные потоки ввода/вывода
Определение потока:
Поток — это конвейер для передачи данных, привитый между программой и устройством, на этом конвейере много кнопок, и разные кнопки могут выполнять разные функции.
Этот пайп для передачи данных — это поток, а стрим — это пайп
При вводе программа открывает поток в источнике (файл, сеть, память) и последовательно читает один за другим, как показано. То же самое касается письма.
Классификация и использование потоков:
Четыре основных абстрактных потока, файловый поток, буферный поток, поток преобразования, поток данных, поток печати, поток объектов.
Несколько типов потоков (классы или абстрактные классы) определены в пакете JAVA.io для реализации функций ввода/вывода; их можно классифицировать с разных точек зрения:
* В зависимости от направления потока данных его можно разделить на входной поток и выходной поток.
* В соответствии с блоком данных обработки его можно разделить на поток байтов и поток символов.
* В соответствии с различными функциями его можно разделить на поток узлов и поток обработки.
Все типы потоков, представленные в JAVA, находятся в пакете JAVA.io и наследуются от следующих четырех абстрактных типов потоков:
Поток узлов и поток обработки:
Потоки узла могут считывать данные из определенного источника данных (узла) (например: файл, память)
Поток обработки «подключен» к существующему потоку (узловому потоку или потоку обработки) и предоставляет более мощные функции чтения и записи для программы путем обработки данных.
Поток узлов также называется исходным потоком, а поток обработки также называется потоком пакетов.
Связь между потоками и классами:
Если класс используется для передачи данных между устройством и программой, класс имеет новое имя, называемое потоком.
Поток должен быть классом, но класс не обязательно является потоком
Введение в четыре элементарных потока
входной поток, выходной поток, байтовый поток, символьный поток
InputStream и OutputStream читают и записывают данные в единице одного байта
Единицей для чтения и записи данных для Reader и Writer является один символ.
Символ занимает два байта в JAVA
InputStream, OutputStream, Reader, Writer — все это абстрактные классы или абстрактные потоки. Обычно мы используем их подклассы. Все, что заканчивается на Stream, — это поток байтов.
Общие методы в потоке InputStream:
Общие методы в потоке OutputStream:
Общие методы в потоках чтения:
Общие методы в потоках Writer:
файловый поток
Файловые потоки включают в себя:
FileInputStream FileOutputStream -- поток байтов
FileReader FileWriter -- поток символов
Пример: прочитать содержимое файла и вывести его на дисплей, а также подсчитать количество прочитанных байтов.
1 /*
2 利用FileReader流来读取一个文件中的数据,并在显示器上输出!
3 */
4
5 import java.io.*;
6
7 public class TestFileReader {
8 public static void main(String[] args) {
9 FileReader fr = null;
10
11 try {
12 fr = new FileReader("C:\\Documents and Settings\\others\\桌面\\java\\TestFileReader.java");
13 int cnt = 0;
14 int ch;
15
16 while (-1 != (ch = fr.read())) // 20行
17 {
18 System.out.print((char) ch); // System.out.print(int ch);
19 // 这是在显示器上输出ch的整数值,所以必须的进行类型转化,我们需要输出的是ch所代表的整数对应的字符
20 ++cnt;
21 }
22
23 System.out.printf("总共从TestFileReader.java文件中读取了%d个字符", cnt);
24 } catch (FileNotFoundException e) {
25 System.out.println("找不到文件!");
26 System.exit(-1);
27 } catch (IOException e) {
28 System.out.println("文件读取失败!");
29 System.exit(-1);
30 }
31 }
32 }
View Code
Использование FileInputStream
Использование FileReader
Разница между потоком байтов и потоком символов:
FileInputStream и FileOutputStream могут выполнять копирование файлов всех форматов.
FileReader и FileWriter могут копировать только текстовые файлы, но не могут копировать файлы других форматов.
Поскольку байты не нужно декодировать и кодировать, возникает проблема декодирования и кодирования при преобразовании байтов в символы.
Потоки байтов могут считывать и записывать данные со всех форматов устройств, а потоки символов могут считывать и записывать данные только с устройств текстового формата.
Пример: программирование для копирования файлов
1 /*
2 利用FileInputStream 和 FileOutputStream 可以完成所有格式文件的赋值
3 因为字节是不需要解码和编码的,将字节转化为字符才存在解码的问题
4 本程序完成了音频文件的复制
5 */
6
7 import java.io.*;
8
9 public class TestFileInputStreamOutputStreamCopy {
10 public static void main(String[] args) {
11 FileInputStream fi = null;
12 FileOutputStream fo = null;
13
14 try {
15 fi = new FileInputStream("E:\\综艺\\歌曲\\卡农.mp3");
16 fo = new FileOutputStream("d:/share/Output.txt"); //使用播放器可正常播放该文件
17 int ch;
18
19 while (-1 != (ch = fi.read())) {
20 fo.write(ch);
21 }
22 } catch (FileNotFoundException e) {
23 System.out.println("文件没有找到!");
24 System.exit(-1);
25 } catch (IOException e) {
26 System.out.println("文件读写错误!");
27 System.exit(-1);
28 } finally {
29 try {
30 if (null != fi) {
31 fi.close();
32 fi = null;
33 }
34 if (null != fo) {
35 fo.close();
36 fo = null;
37 }
38 } catch (Exception e) {
39 e.printStackTrace();
40 System.exit(-1);
41 }
42 }
43
44 System.out.println("文件复制成功!");
45 }
46 }
TestFileInputStreamOutputStreamCopy
1 /*
2 本程序证明了 FileReader 和 FileWriter 只可以完成文本文件的复制,
3 却无法完成音频格式文件的复制
4 */
5
6 import java.io.*;
7
8 public class TestFileReaderWriterCopy {
9 public static void main(String[] args) {
10 FileReader fi = null;
11 FileWriter fo = null;
12
13 try {
14 fi = new FileReader("E:\\综艺\\歌曲\\卡农.mp3");
15 fo = new FileWriter("d:/share/Output.txt"); // Output.txt使用播放器打开失败!
16 // 本程序证明了FileWriter 和
17 // FileReader
18 // 无法完成音频文件的复制,实际上FileWriter
19 // 和 FileReader
20 // 只能完成文本文件的复制
21 int ch;
22
23 while (-1 != (ch = fi.read())) {
24 fo.write(ch);
25 }
26 } catch (FileNotFoundException e) {
27 System.out.println("文件没有找到!");
28 System.exit(-1);
29 } catch (IOException e) {
30 System.out.println("文件读写错误!");
31 System.exit(-1);
32 } finally {
33 try {
34 if (null != fi) {
35 fi.close();
36 fi = null;
37 }
38 if (null != fo) {
39 fo.close();
40 fo = null;
41 }
42 } catch (Exception e) {
43 e.printStackTrace();
44 System.exit(-1);
45 }
46 }
47
48 System.out.println("文件复制成功!");
49 }
50 }
TestFileReaderWriterCopy
буферизованный поток
Буферизованный поток — это входной и выходной поток с буфером.
Буферизованные потоки могут значительно сократить количество операций ввода-вывода, которые мы делаем, и защитить наши жесткие диски.
Буферизованные потоки предназначены для обработки потоков (обернутые потоки), а буферизованные потоки должны быть присоединены к потокам узла (исходные потоки).
Обработка потока, обернутого вокруг исходного потока узла, эквивалентного конвейеру, обернутому вокруг канала.
Буферизованный поток должен быть «сокетирован» на соответствующем потоке узла, что обеспечивает функцию буферизации читаемых и записываемых данных, повышает эффективность чтения и записи и добавляет некоторые новые методы. JAVA предоставляет четыре буферных потока, и обычно используются следующие методы построения:
BufferedOutputStream и BufferedInputStream
BufferedOutputStream: буферизованный выходной поток, который позволяет одновременно записывать на диск несколько байтов данных.
BufferedInputStream: буферизованный входной поток, который позволяет одновременно считывать в программу несколько байтов данных.
BufferedOutputStream и BufferedInputStream являются обернутыми потоками и должны быть присоединены к OutputStream и InputStream.
Пример. Используйте BufferedOutputStream и BufferedInputStream для копирования файлов большого объема, что намного быстрее, чем простое использование FileInputStream и FileOutputStream.
1 /*
2 利用BufferedOutputStream 和 BufferedInputStream完成大容量文件的复制
3 这远比单纯利用 FileInputStream 和 FileOutputStream 要快得多
4
5 BufferedOutputStream 和 BufferedInputStream 都是包裹流,必须的依附于
6 InputStream 和 OutputStream
7 */
8
9 import java.io.*;
10
11 public class TestBufferedInputStreamOutputStreamCopy {
12 public static void main(String[] args) {
13 BufferedOutputStream bos = null;
14 BufferedInputStream bis = null;
15
16 try {
17 bos = new BufferedOutputStream(new FileOutputStream("e:/OutputView.txt")); // bos
18 // 输出流有个默认的缓冲区,大小为32个字节
19
20 bis = new BufferedInputStream(new FileInputStream("c:\\[高清在线www.66ys.cn]海底总动员DVD中英字幕.rmvb")); // bis
21 // 输入流有个默认的缓冲区,大小为32个字节
22 byte[] buf = new byte[1024];
23 int len = bis.read(buf, 0, 1024); // 一定要注意,这不是从buf中读数据,而是从bis所关联到的D:\\综艺\\电影\\猫和老鼠\\CD4.rmvb文件中读取数据,并将读取的数据写入bis自己的默认缓冲区中,然后再将缓冲区的内容写入buf数组中,每次最多向buf数组中写入1024个字节,返回实际写入buf数组的字节个数,如果读到了文件的末尾,无法再向buf数组中写入数据,则返回-1
24 while (-1 != len) {
25 bos.write(buf, 0, len); // 不是写入buf数组,而是将buf数组中下标从0开始的到len-1为止的所有数据写入bos所关联到的"d:/share/OutputView.txt"文件中
26 len = bis.read(buf); // bis.read(buf); 等价于 bis.read(buf, 0,
27 // buf.length);
28 }
29 bos.flush();
30 bis.close();
31 bos.close();
32 } catch (FileNotFoundException e) {
33 System.out.println("没有找到文件!");
34 System.exit(-1);
35 } catch (IOException e) {
36 System.out.println("文件读写错误!");
37 System.exit(-1);
38 }
39
40 System.out.println("文件复制成功!");
41 }
42 }
TestBufferedInputStreamOutputStreamCopy
1 /*
2 本程序读写速度要慢于 "TestBufferedInputStreamOutputStreamCopy.java" 程序
3 即:
4 利用BufferedOutputStream 和 BufferedInputStream完成大容量文件的复制
5 这远比单纯利用 FileInputStream 和 FileOutputStream 要快得多
6
7 BufferedOutputStream 和 BufferedInputStream 都是包裹流,必须的依附于
8 OutputStream 和 OutputStream
9 */
10
11 import java.io.*;
12
13 public class TestBufferedInputStreamOutputStreamCopy_2 {
14 public static void main(String[] args) {
15 FileOutputStream bos = null;
16 FileInputStream bis = null;
17
18 try {
19 bos = new FileOutputStream("e:/OutputView.txt");
20 bis = new FileInputStream("c:\\[高清在线www.66ys.cn]海底总动员DVD中英字幕.rmvb");
21
22 byte[] buf = new byte[1024];
23 int len = bis.read(buf, 0, 1024);
24 while (-1 != len) {
25 bos.write(buf, 0, len);
26 len = bis.read(buf);
27 }
28 bos.flush();
29 bis.close();
30 bos.close();
31 } catch (FileNotFoundException e) {
32 System.out.println("没有找到文件!");
33 System.exit(-1);
34 } catch (IOException e) {
35 System.out.println("文件读写错误!");
36 System.exit(-1);
37 }
38
39 System.out.println("文件复制成功!");
40 }
41 }
TestBufferedInputStreamOutputStreamCopy_2
Следует отметить, что bis.read(buf,0,1024); это чтение данных не из buf, а из "D:\\variety\\movie\\cat and mouse\\CD4.rmvb, связанного с bis" Read данные из файла и записать считанные данные в буфер по умолчанию bis, а затем записать содержимое буфера в массив buf, каждый раз записывая максимум 1024 байта в массив buf. Возвращает количество фактически записанных байтов. в массив buf или -1, если прочитан конец файла и в массив buf больше нельзя записать данные
В потоке BufferedInputStream существует общедоступный метод int read(byte[] b) для сохранения данных, считанных с устройства, связанного с текущим потоком, в массив байтов.
В потоке BufferedOutputStream есть общедоступный метод int write(byte[] b), который используется для вывода данных в массиве байтов на устройство, связанное с текущим потоком.
Если мы хотим использовать BufferedInputStream и BufferedOutputStream для завершения «импорта данных с одного устройства на другое устройство», мы должны определить временный байтовый тип данных и использовать этот временный массив в качестве транзитного концентратора для взаимодействия между входным потоком и выходным. поток.
BufferedReader и BufferedWriter
Пример: копирование текстовых файлов с помощью BufferedReader и BufferedWriter
1 /*
2 利用 BufferedReader 和 BufferedWriter 完成文本文件的复制
3 */
4 import java.io.*;
5
6 public class TestBufferedReaderWriterCopy {
7 public static void main(String[] args) {
8 BufferedReader br = null;
9 BufferedWriter bw = null;
10
11 try {
12 br = new BufferedReader(
13 new FileReader("C:\\Documents and Settings\\others\\桌面\\java\\TestBufferedReaderWriterCopy.java"));
14 bw = new BufferedWriter(new FileWriter("d:/share/Writer.txt"));
15 String str = null;
16
17 while (null != (str = br.readLine())) // br.readLine()读取一行字符,但会将读取的换行符自动丢弃,即返回的String对象中并不包括换行符
18 {
19 bw.write(str);
20 bw.newLine(); // 写入一个换行符 这行不能省
21 }
22 bw.flush();
23 } catch (FileNotFoundException e) {
24 e.printStackTrace();
25 System.exit(-1);
26 } catch (IOException e) {
27 e.printStackTrace();
28 System.exit(-1);
29 } finally {
30 try {
31 bw.close();
32 br.close();
33 } catch (IOException e) {
34 e.printStackTrace();
35 System.exit(-1);
36 }
37 }
38 }
39 }
TestBufferedReaderWriterCopy
поток данныхDataInputStream DataOutputStream
DataInputStream может считывать данные примитивных типов JAVA и типов String непосредственно из базового потока ввода байтов машинно-независимым способом. Общие методы включают в себя:
DataInputStream является потоком-оболочкой и должен быть присоединен к InputStream.
DataOutputStream может напрямую записывать данные примитивного типа JAVA и данные типа String в другие потоки вывода байтов машинно-независимым способом. Общие методы включают в себя:
DataOutputStream — это обернутый поток, он должен быть присоединен к OutputStream.
Пример потока данных:
Программная реализация записывает данные длинного типа в массив байтов, а затем считывает данные из массива байтов {
*Эта функция часто используется при программировании сокетов.
*Поскольку в сетевом программировании данные часто хранятся в массиве байтов, а затем массив байтов упаковывается в пакет данных (DatagramPacket), а затем пакет данных передается на машину назначения через сеть, а машина назначения затем преобразует исходные числовые данные из байтового массива, восстанавливает обратно.
}
Эта программа использует:
DataInputStream
DataOutputStream
ByteArrayInputStream
ByteArrayOutputStream
1 /*
2 功能:把一个long类型的数据写入byte数组中,然后再从byte数组中读取出
3 这个long类型的数据
4
5 因为网络编程中经常要把数值型数据存入byte数组中然后打包成
6 DatagramPacket经过网络传输到目的机,目的机再从byte数组中
7 把原数值型数据还原回来
8
9 目的: ByteArrayOutputStream DataOutputStream ByteInputStream DataInputStream 流的使用
10 记住: DataOutputStream流中的writeLong(long n)是把n变量在内存
11 中的二进制代码写入该流所连接到的设备中
12
13 注意:查API文档得知:
14 构造 ByteArrayOutputStream 对象时不需要也不能指定缓冲数组,因为缓冲数组默认已经内置好了
15 构造 ByteArrayInputStream 对象时必须的指定缓冲数组是谁!
16 */
17
18 import java.io.*;
19
20 public class TestByteArrayOutputStream1
21 {
22 public static void main(String args[]) throws Exception
23 {
24 long n = 9876543210L;
25 ByteArrayOutputStream baos = new ByteArrayOutputStream(); //9行 API:"public ByteArrayOutputStream(): 创建一个新的 byte 数组输出流。缓冲区的容量最初是 32 字节,如有必要可增加其大小。 "
26 //9行代码一旦执行完毕,意味着两点: 1、在内存中生成了一个大小为32个字节的byte数组 2、有一根叫做baos的管道已链接到了该byte数组中,并且可以通过这个管道向该byte数组中写入数据
27 //虽然此时可以通过baos向baos所连接到的在内存中分配好的byte数组中写入数据,但是ByteArrayOutputStream流并没有提供可以直接把long类型数据直接写入ByteArrayOutputStream流所连接到的byte数组中的方法, 简单说我们没法通过baos向baos所连接到的byte数组中写入long类型的数据, 查API文档可以发现: ByteArrayOutputStream流中并没有类似writeLong()这样的方法,但是DataOutputStream流中却有writeLong() writeFloat()等方法
28 DataOutputStream dos = new DataOutputStream(baos);
29
30 dos.writeLong(n); //把n变量所代表的10000L在内存中的二进制代码写入dos所依附的baos管道所连接到的内存中的大小为32字节的byte数组中,由运行结果来看,这是二进制写入,既不是把10000L转化为字符'1' '0' '0' '0' '0'写入byte数组中,而是把10000L在内存中的总共8个字节的二进制代码写入byte数组中
31
32 dos.flush();
33 byte[] buf = baos.toByteArray(); //DataOutputStream 流中并没有toByteArray()方法,但是ByteArrayOutputStream 流中却有toByteArray()方法, 所以不可以把baos 改为dos,否则编译时会出错! ByteArrayOutputStream流中toByteArray()方法的含义,摘自API“创建一个新分配的 byte 数组。其大小是此输出流的当前大小,并且缓冲区的有效内容已复制到该数组中”
34
35 //利用ByteArrayInputStream 和 DataInputStream 可以从byte数组中得到原long类型的数值10000L
36 ByteArrayInputStream bais = new ByteArrayInputStream(buf);
37 DataInputStream dis = new DataInputStream(bais);
38 long l = dis.readLong();
39
40 System.out.println("l = " + l);
41 dos.close();
42 }
43 }
44 /*
45 在JDK 1.6中的运行结果是:
46 ----------------
47 l = 9876543210
48 ----------------
49 */
TestByteArrayOutputStream1
1 /*
2 功能:
3 将long类型数据写入byte数组,然后在从byte数组中把该数据读出来
4 */
5
6 import java.io.*;
7
8 public class TestByteArrayOutputStream2
9 {
10 public static void main(String[] args) throws Exception
11 {
12 long n = 1234567;
13 ByteArrayOutputStream baos = new ByteArrayOutputStream();
14 DataOutputStream dos = new DataOutputStream(baos);
15 dos.writeLong(n);
16
17 byte[] buf = baos.toByteArray();
18 ByteArrayInputStream bis = new ByteArrayInputStream(buf);
19 DataInputStream dis = new DataInputStream(bis);
20 long n2 = dis.readLong();
21 System.out.println("n2 = " + n2);
22
23 dos.close();
24 dis.close();
25 }
26 }
TestByteArrayOutputStream2
Преобразование потоков: OutputStreamWriter InputStreamReader
Поток OutputStreamWriter — это поток, который преобразует поток OutputStream в поток Writer.
Поток InputStreamReader предназначен для преобразования потока InputStream в Reader.
OutputStreamWriter и InputStreamReader являются обернутыми потоками.
Пример: Как напрямую назначить символы, введенные с клавиатуры в строку, объекту String.
1 /*
2 如何将键盘输入的字符组成字符串直接赋给String 对象
3
4 预备知识:
5 --------------------------------
6 Reader FileReader InputStream FileInputStream BufferedInputStream
7 流中都没有 readLine 方法
8 DataInputStream 流中有 readLine方法,但已经 被标记为过时
9 BufferedReader 流中有readLine方法,并且该方法是可以正确被使用的
10 --------------------------------
11 */
12
13 import java.io.*;
14
15 public class TestStringInput
16 {
17 public static void main(String[] args)
18 {
19 String str = null;
20 BufferedReader br = new BufferedReader ( //21行
21 new InputStreamReader(System.in)
22 ); //23行 查API:从21行到23行的代码是不会抛出任何异常的
23
24 try
25 {
26 str = br.readLine(); //会抛出IOException异常
27 }
28 catch (IOException e)
29 {
30 e.printStackTrace();
31 System.exit(-1);
32 }
33
34 System.out.println("str = " + str);
35 try
36 {
37 br.close(); //会抛出IOException异常
38 }
39 catch (IOException e)
40 {
41 e.printStackTrace();
42 System.exit(-1);
43 }
44 }
45 }
46 /*
47 在JDK 1.6中的运行结果是:
48 --------------------------------
49 sadd行政村123Asd?asd撒旦
50 str = sadd行政村123Asd?asd撒旦
51 --------------------------------
52 */
TestStringInput
Проблемы с readLine() и возвратом каретки:
Поток печати PrintWriter PrintStream
Поток печати имеет только вывод, без ввода
Классификация:
Символы ввода PrintWriter
PrintStream выводит символы
PrintWriter предоставляет расширенные функции на основе OutputStream, которые могут легко выводить форматированные представления различных типов данных (не ограничиваясь типами байтов).
PrintStream перегружает методы print и println для форматированного вывода различных типов данных.
Форматированный вывод относится к выводу данных в строковом формате.
Метод WriteXXX(data) в DataOutputStream предназначен для записи двоичных данных данных в памяти в файл.
println(data) в PrintStream — это форматированная строка данных, записанных в файл.
1 /*
2 DataOutputStream 中的 writeXXX(data)方法
3 与
4 PrintStream 中的 println(data)的区别
5
6 总结:
7 DataOutputStream 中的 writeXXX(data)方法是把data在内存中的二进制数据写入文件
8 PrintStream 中的 println(data)写出的是该数据的格式化后的字符串
9 */
10
11 import java.io.*;
12
13 public class TestPrintStream_1
14 {
15 public static void main(String[] args) throws Exception
16 {
17 DataOutputStream dos = new DataOutputStream(new FileOutputStream("d:/share/kk.txt"));
18 dos.writeLong(12345); //实际写入文件的是00 00 00 00 00 00 30 39
19 dos.close();
20 System.out.printf("%#X\n", 12345);
21
22 PrintStream ps = new PrintStream(new FileOutputStream("d:/share/kk2.txt"), true);
23 ps.println(12345); //实际写入文件的是'1' '2' '3' '4' '5'
24 ps.close();
25 }
26 }
TestPrintStream_1
PrintWriter предоставляет все методы печати PrintStream, и его методы никогда не вызывают исключение IOException.
Отличие от PrintStream:
Перенаправление стандартного ввода и вывода:
Пример: Программа для ввода данных, введенных с клавиатуры, в файл A. Если ввод неправильный, информация об ошибке будет выведена в файл B.
1 import java.io.*;
2
3 public class TestSetSystemOut {
4 public static void main(String[] args) {
5 PrintStream ps_out = null;
6
7 try {
8 ps_out = new PrintStream(new FileOutputStream("d:/share/ww.txt"));
9 System.setOut(ps_out); // 将System.out的值重新设置为ps_out,即System.out不在关联到显示器,而是关联到"d:/share/ww.txt"文件
10 System.out.println(12); // 这实际上是把12输出到了System.out所关联的d:/share/ww.txt中
11 System.out.println(55.5); // 同上
12 } catch (Exception e) {
13 e.printStackTrace();
14 } finally {
15 try {
16 ps_out.close();
17 } catch (Exception e) {
18 e.printStackTrace();
19 }
20
21 }
22 }
23 }
TestSetSystemOut
1 /*
2 功能: 将键盘输入的数据输入A文件中,如果输入有误,
3 则把出错信息输出到B文件中
4
5 标准输入输出流的重定向
6 */
7
8 import java.io.*;
9 import java.util.*;
10
11 public class TestSetOutErr {
12 public static void main(String[] args) {
13 PrintStream psOut = null;
14 PrintStream psError = null;
15 Scanner sc = null;
16
17 try {
18 psOut = new PrintStream("d:/Out.txt");
19 psError = new PrintStream("d:/error.txt");
20 sc = new Scanner(System.in);
21 int num;
22 System.setOut(psOut);
23 System.setErr(psError);
24
25 while (true) {
26 num = sc.nextInt();
27 System.out.println(num);
28 }
29 } catch (Exception e) {
30 System.err.println("出错的信息是:"); // 不可以写成System.out.println("出错的信息是:");
31 e.printStackTrace(); // e.printStackTrace(); 默认是输出到System.err所关联的设备中
32 }
33 }
34 }
TestSetOutErr
Сериализация объектов ObjectOutputStream ObjectInputStreamТак называемая сериализация означает: преобразование объекта Object непосредственно в поток байтов, а затем запись потока байтов непосредственно на локальный жесткий диск или в поток сетевой сериализации (ObjectOutputStream) ---- поток десериализации writeObject (ObjectInputStream)- - -readObject Если вы хотите сериализовать объект, вы должны реализовать интерфейс Serializable.После того, как ключевое слово transient используется для изменения переменной, переменная не будет сериализована по умолчанию jvm.Когда мы хотим преобразовать объект в последовательность байтов для передачи по сети, некоторые из наших переменных не нужно использовать, и передача по сети приведет к пустой трате ресурсов. В настоящее время мы будем использовать переходное ключевое слово переходный для изменения свойств. Мы можем выполнить сериализацию самостоятельно. В некоторых случаях ключевое слово переходного процесса может повысить производительность
Пример:
1 import java.io.*;
2
3 public class TestObjectIO
4 {
5 public static void main(String[] args)
6 {
7 ObjectOutputStream oos = null;
8 ObjectInputStream ois = null;
9 Student ss = new Student("zhansan", 1000, 88.8f); //注意88.8f不能改为88.8
10 Student ss2 = null;
11
12 try
13 {
14 FileOutputStream fos = new FileOutputStream("d:/share/java/ObjectOut.txt");
15 oos = new ObjectOutputStream(fos);
16 oos.writeObject(ss);
17
18 ois = new ObjectInputStream(new FileInputStream("d:/share/java/ObjectOut.txt"));
19 ss2 = (Student)ois.readObject(); //(Student)不能省 ois.readObject();如果ois中的某个成员是transient,则该成员是不会被读取的,因为该成员不会被保存,何来读取之说?!
20
21 System.out.println("ss2.sname = " + ss2.sname);
22 System.out.println("ss2.sid = " + ss2.sid);
23 System.out.println("ss2.sscore = " + ss2.sscore);
24 }
25 catch (FileNotFoundException e)
26 {
27 System.out.println("文件没有找到!");
28 System.exit(-1);
29 }
30 catch (Exception e)
31 {
32 e.printStackTrace();
33 System.exit(-1);
34 }
35 finally
36 {
37 try
38 {
39 oos.close();
40 ois.close();
41 }
42 catch (Exception e)
43 {
44 e.printStackTrace();
45 System.exit(-1);
46 }
47 }
48 }
49 }
50
51 class Student implements Serializable //如果将implements Serializable 注释掉,则程序编译时就会报错
52 {
53 public String sname = null;
54 public int sid = 0;
55 transient public float sscore = 0; //表示sscore成员不能被序列化,所谓不能被序列化就是指:“该成员调用ObjectOutputStream 的writeOnbject()时不会被保存,调用ObjectInputStream的readObject()方法时不会被读取”
56
57 public Student(String name, int id, float score)
58 {
59 this.sname = name;
60 this.sid = id;
61 this.sscore = score;
62 }
63 }
TestObjectIO Анализ проблем сериализации и десериализации в исходном коде ArrayListХотя нижний слой ArrayList представляет собой массив, этот массив не обязательно является полным. Элементы массива, которые не заполнены, не нуждаются в сериализации. Мы должны выполнить сериализацию самостоятельно, а также завершить сериализацию и десериализацию допустимых элементов. элементы один за другим. То же самое верно, поэтому функция сериализации и десериализации в исходном коде ArrayList заключается в сериализации допустимых элементов в ArrayList, а не в сериализации недопустимых элементов, что может повысить производительность. иметь предварительное представление об исходном коде ArrayList и может оптимизировать проблему сериализации;
Проблема вызова конструктора подкласса и родительского класса при сериализацииКогда родительский класс подкласса реализует интерфейс сериализации, подкласс может быть сериализован напрямую, а конструктор родительского класса будет рекурсивно вызываться при сериализации подкласса. При десериализации объекта подкласса, если его родительский класс не реализует интерфейс сериализации, будет вызван конструктор его родительского класса