основное содержание
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.
Пример:
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 и может оптимизировать проблему сериализации;
Проблема вызова конструктора подкласса и родительского класса при сериализацииКогда родительский класс подкласса реализует интерфейс сериализации, подкласс может быть сериализован напрямую, а конструктор родительского класса будет рекурсивно вызываться при сериализации подкласса. При десериализации объекта подкласса, если его родительский класс не реализует интерфейс сериализации, будет вызван конструктор его родительского класса