您的位置:首页 > 编程语言 > Java开发

JAVA基础之IO操作

2016-03-09 23:07 471 查看


文件 - File类

File对象
1、用来将文件或者文件夹封装成对象
2、方便对文件与文件夹的属性信息进行操作
3、File对象可以作为参数传递给流的构造函数

public class Test {
public static void main(String[] args) {
File f = new File("e:\\");
System.out.println(new File("e:\\demo.txt"));
System.out.println(new File("e:\\", "demo.txt"));
System.out.println(new File(f, "demo.txt"));
System.out.println(new File("e:" + File.separator + "demo.txt"));
}
}
/** 输出
e:\demo.txt
e:\demo.txt
e:\demo.txt
e:\demo.txt
*/

File对象 - 常见功能

1.获取
1.1 获取文件名称 - getName()
1.2 获取文件路径 - getPath()/getAbsolutePath()
1.3 获取文件大小 - length()
1.4 获取文件修改时间 - lastModified()


2.创建与删除
2.1 创建文件 - createNewFile():和输出流不一样,如果文件不存在,则创建,如果文件存在,则不创建
- mkdir():创建目录
2.2 删除文件 - delete():当使用delete()删除目录时,如果不是空文件夹会删除失败
- deleteOnExit():在虚拟机终止时,请求删除此抽象路径名表示的文件或目录


3.判断
3.1 判断是否存在 - exists()
3.2 判断是否是目录 - isDirectory()
3.3 判断是否是文件 - isFile()


4.重命名
4.1 重命名 - renameTo(File dest)


5.列出目录和容器获取
5.1 获取可用的文件系统根 - listRoots()
5.2 获取抽象路径名指定的分区大小 - getTotalSpace()
5.3 获取抽象路径名指定的分区中未分配的字节数 - getFreeSpace()
5.4 获取抽象路径名指定的分区上可用于此虚拟机的字节数 - getUsableSpace()
5.5 获取目录中的文件和目录,包含隐藏文件 - String[] list() =>只能通过目录去调用,否则空指针异常,如果目录存在但没有内容,则返回长度为0的数组
5.6 获取目录中按照特定过滤器过滤后的文件和目录 - String[] list(FilenameFilter filter)

实例
public class Test {
public static void main(String[] args) throws IOException {
File file = new File("demo.txt");
File absFile = new File("C:\\Users\\Administrator\\workspace\\HelloJava\\demo.txt");

String name = file.getName();
String absPath = file.getAbsolutePath();
String path = file.getPath();
long length = file.length();

long time = file.lastModified();
String lastModifiedTime = getTime(time);

String parentPath = file.getParent();
String absFileParentPath = absFile.getParent();

System.out.println("parentPath:" + parentPath + " ==> absFileParentPath:"
+ absFileParentPath);

// 删除创建文件
file.delete();
file.createNewFile();
System.out.println("lastModifiedTime:" + lastModifiedTime + " ==> new:"
+ getTime(file.lastModified()));

File dir = new File("test\\a\\b\\c");
// 创建目录
dir.mkdir();
dir.delete(); // 如果c不是空文件夹,将删除失败;并且只能删除c文件夹

// 文件或目录是否存在
boolean isExist = file.exists();
boolean isAbsolute = file.isAbsolute();
boolean isFile = file.isFile();
boolean isDir = dir.isDirectory();

File dest = new File("text.txt");
// 重命名
file.renameTo(dest);
// 剪切
dest.renameTo(new File("e:\\abc.txt"));

File[] files = File.listRoots();
for (File f : files) {
long free = f.getFreeSpace();
long total = f.getTotalSpace();
// 返回此抽象路径名指定的分区上可用于此虚拟机的字节数
long usable = f.getUsableSpace();
}

// list方法只能使用目录去调用,文件调用会返回null
String[] list = absFile.list();
System.out.println(file.list());

File workspace = new File("C:\\Users\\Administrator\\workspace\\HelloJava");
list = workspace.list(new SuffixFilter(".txt"));
for (String string : list) {
System.out.println(string);
}

files = workspace.listFiles(new FilterByHidden());
for (File f : files) {
System.out.println(f);
}

}

private static String getTime(long time) {
Date date = new Date(time);
DateFormat format = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
return format.format(date);
}
}

class SuffixFilter implements FilenameFilter {
private String suffix = null;

public SuffixFilter(String suffix) {
super();
this.suffix = suffix;
}

public boolean accept(File dir, String name) {
return name.endsWith(suffix);
}
}

class FilterByHidden implements FileFilter {
public boolean accept(File pathname) {
return pathname.isHidden();
}
}

/**
* 输出 :
parentPath:null ==> absFileParentPath:C:\Users\Administrator\workspace\HelloJava
lastModifiedTime:16-2-17 下午10:11 ==> new:16-2-17 下午10:18
null
demo.txt
fileWriter.txt
text.txt
*/

// 深度遍历目录
public class Test {
public static void main(String[] args) throws IOException {
File dir = new File("C:\\Users\\Administrator\\workspace\\HelloJava\\bin");
listAll(dir, 0);
deleteAll(dir);
}

// 深度遍历目录
private static void listAll(File dir, int level) {
File[] files = dir.listFiles();
level++;
for (int i = 0; i < files.length; i++) {
if (files[i].isDirectory()) {
// 递归调用,一个功能在被重复使用,并每次使用时参与运算的结果和上一次调用有关
// 注意:
// 1.递归一定明确条件,否则容易栈溢出
// 2.注意一下递归次数
listAll(files[i], level);
} else {
System.out.println(level + ":" + files[i].getAbsolutePath());
}
}
}

// 删除目录,需要从里往外删除
private static void deleteAll(File dir) {
File[] files = dir.listFiles();
for (int i = 0; i < files.length; i++) {
if (files[i].isDirectory()) {
deleteAll(files[i]);
} else {
files[i].delete();
}
}
dir.delete();
}
}

// 文件切割、合并
public class Test {
private static final int SIZE = 1024;

public static void main(String[] args) throws IOException {
File file = new File("e:\\tone.mp3");
spitFile(file);

mergeFile(new File("e:\\test"));
}

// 文件切割
private static void spitFile(File file) throws IOException {
FileInputStream fis = new FileInputStream(file);

Properties prop = new Properties();

byte[] buff = new byte[SIZE * 100];

FileOutputStream fos = null;

int len = 0;
int count = 1;

File dir = new File("e:\\test");
if (!dir.exists()) {
dir.mkdir();
}

while ((len = fis.read(buff)) != -1) {
fos = new FileOutputStream(new File(dir, (count++) + ".part"));
fos.write(buff, 0, len);
fos.close();
}

// 将文件切割信息保存到属性中
prop.setProperty("count", count + "");
prop.setProperty("name", file.getName());

// 将属性保存到.prop 配置信息中
fos = new FileOutputStream(new File(dir, (count++) + ".prop"));
prop.store(fos, "save file prop");

fos.close();
fis.close();
}

// 文件合并
private static void mergeFile(File dir) throws IOException {
File[] files = dir.listFiles(new SuffixFilter(".prop"));

if (files.length != 1) {
throw new RuntimeException("Filename not match..");
}

File config = files[0];

// 获取配置文件信息
Properties prop = new Properties();
FileInputStream fis = new FileInputStream(config);

prop.load(fis);

String name = prop.getProperty("name");
int count = Integer.parseInt(prop.getProperty("count"));

File[] parts = dir.listFiles(new SuffixFilter(".part"));
if (parts.length != count - 1) {
throw new RuntimeException("Part length not match..");
}

ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();

for (int i = 1; i < count; i++) {
al.add(new FileInputStream(new File(dir, i + ".part")));
}

Enumeration<FileInputStream> en = Collections.enumeration(al);
SequenceInputStream sis = new SequenceInputStream(en);

FileOutputStream fos = new FileOutputStream(new File(dir, name));

byte[] buff = new byte[SIZE * 100];
int len = 0;

while ((len = sis.read(buff)) != -1) {
fos.write(buff, 0, len);
}

fos.close();
sis.close();
}
}

class SuffixFilter implements FilenameFilter {
private String suffix = null;

public SuffixFilter(String suffix) {
super();
this.suffix = suffix;
}

public boolean accept(File dir, String name) {
return name.endsWith(suffix);
}
}


流分类

按流向分为:输入流与输出流
输入流和输出流相对于内存设备而言

输入:将外设中的数据读取到内存中
输出:将内存中国的数据写入到外设中

按照操作数据分为:字节流与字符流
字符流的由来:字节流读取文字字节数据后,不直接操作而是先查指定的编码表,获取对应的文字,再对这个文字进行操作
简单说:字符流 = 字符流+编码表

IO体系的子类都以父类名作为后缀,而且子类名的前缀就是该对象的功能


字符流 - Reader/Writer

如果要操作文字数据,建议优先考虑字符流,而且要将数据从内存写到硬盘上,要使用字符流中的输出流-Writer,硬盘的数据基本体现是文件



字符流 - 写入文件(FileWriter)
public class Test {
// 换行
private static final String LINE_SEPARATOR = System.lineSeparator();

public static void main(String[] args) throws IOException {
File file = new File("e:\\fileWriter.txt");
fileWrite(file, "FileWriter");
}

private static void fileWrite(File path, String input) throws IOException {
// 如果文件不存在,则创建;如果文件存在,则覆盖
FileWriter writer = new FileWriter(path);
//FileWriter writer = new FileWriter(path, true); //续写构造函数
// FileWriter(File file, boolean append):续写
// 写入数据
writer.write(input + LINE_SEPARATOR);
// 进行刷新,将数据直接写到目的地中
writer.flush();
writer.append(input + LINE_SEPARATOR);
// 在关闭前会调用flush()刷新缓冲池中的数据到目的地
writer.close();
}
}

字符流 - 读取文件(FileReader)
public class Test {
public static void main(String[] args) {
File file = new File("e:\\demo.txt");
System.out.println(readFile(file));
}

private static String readFile(File path) {
FileReader reader = null;
StringBuilder builder = new StringBuilder();
try {
reader = new FileReader(path);
int ch = 0;
while ((ch = reader.read()) != -1) {
builder.append((char) ch);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (reader != null)
reader.close();
} catch (IOException e) {
throw new RuntimeException("Close fail!");
}
}
return builder.toString();
}
}

字符流 - 文件读写操作(复制)
public class Test {
public static void main(String[] args) {
File in = new File("e:\\demo.txt");
File out = new File("e:\\copy.txt");
copyFile(in, out);
}

private static void copyFile(File in, File out) {
FileReader reader = null;
FileWriter writer = null;

try {
/* 效率较低
reader = new FileReader(in);
writer = new FileWriter(out);
int ch = 0;
while ((ch = reader.read()) != -1) {
writer.write(ch);
}
*/
reader = new FileReader(in);
writer = new FileWriter(out);
char[] ch = new char[1024];
int len = 0;
while ((len = reader.read(ch)) != -1) {
writer.write(ch, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (reader != null) {
reader.close();
}
if (writer != null) {
writer.close();
}
} catch (IOException e) {
throw new RuntimeException("Close fail!");
}
}
}
}

字符流 - 缓冲区(BufferedWriter/BufferedReader)
特点:
1. 缓冲区的出现提供了对数据的读写效率
2. 缓冲区要结合流才可以使用
3. 在流的基础上对流的功能进行了增强

BufferedReader:从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
public String readLine():读取一个文本行。通过下列字符之一即可认为某行已终止:换行 ('\n')、回车 ('\r') 或回车后直接跟着换行。

BufferedWriter:将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
public void newLine():写入一个行分隔符。行分隔符字符串由系统属性 line.separator 定义,并且不一定是单个新行 ('\n') 符。

BufferedReader 使用了装饰模式
装饰设计模式:对一组对象的功能进行增强时,就可以使用该模式进行问题的解决

装饰比继承灵活
特点:装饰类和被装饰类都必须所属同一个接口或者父类

public class Test {
public static void main(String[] args) {
File in = new File("e:\\demo.txt");
File out = new File("e:\\copy.txt");
copyFile(in, out);
}

private static void copyFile(File in, File out) {
FileReader reader = null;
BufferedReader bufReader = null;

FileWriter writer = null;
BufferedWriter bufWriter = null;

try {
reader = new FileReader(in);
bufReader = new BufferedReader(reader);

writer = new FileWriter(out);
bufWriter = new BufferedWriter(writer);

String line = null;
while ((line = bufReader.readLine()) != null) {
bufWriter.write(line);
bufWriter.newLine();
bufWriter.flush();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bufReader != null) {
bufReader.close();
}
if (bufWriter != null) {
bufWriter.close();
}
} catch (IOException e) {
throw new RuntimeException("Close fail!");
}
}
}
}

// 自定义BufferedReader
public class Test {
public static void main(String[] args) {
File file = new File("e:\\demo.txt");
readFile(file);
}

private static void readFile(File file) {
FileReader reader = null;
CustomBufferedReader bufReader = null;

try {
reader = new FileReader(file);
bufReader = new CustomBufferedReader(reader);

String line = null;
while ((line = bufReader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bufReader != null) {
bufReader.close();
}
} catch (IOException e) {
throw new RuntimeException("Close fail!");
}
}
}
}

class CustomBufferedReader {
char[] buffer = new char[1024];
Reader reader = null;
private int count = 0;
private int pos = 0;

CustomBufferedReader(Reader reader) {
this.reader = reader;
}

public int read() throws IOException {
if (count == 0) {
count = reader.read(buffer);
pos = 0;
}
if (count < 0) {
return -1;
}
char ch = buffer[pos++];
count--;
return ch;
}

public String readLine() throws IOException {
StringBuilder sb = new StringBuilder();
int ch = 0;
while ((ch = read()) != -1) {
if (ch == '\r')
continue;
if (ch == '\n')
return sb.toString();
sb.append((char) ch);
}
if (sb.length() > 0)
return sb.toString();
return null;
}

public void close() throws IOException {
reader.close();
}
}

字符流 - 缓冲区(BufferedReader子类:LineNumberReader)
public class Test {
public static void main(String[] args) {
File file = new File("e:\\demo.txt");
readFile(file);
}

private static void readFile(File file) {
FileReader reader = null;
LineNumberReader bufReader = null;

try {
reader = new FileReader(file);
bufReader = new LineNumberReader(reader);

String line = null;
bufReader.setLineNumber(2);
while ((line = bufReader.readLine()) != null) {
System.out.println(bufReader.getLineNumber() + ":" + line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bufReader != null) {
bufReader.close();
}
} catch (IOException e) {
throw new RuntimeException("Close fail!");
}
}
}
}

转换流 - InputStreamReader/OutputStreamWriter
转换流 - 字节转字符
InputStreamReader:是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。

转换流 - 字符转字节
OutputStreamWriter:是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。
它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。

public class Test {
public static void main(String[] args) {
try {
readFromKeyboard();
} catch (IOException e) {
e.printStackTrace();
}
}

private static void readFromKeyboard() throws IOException {
/*
InputStream is = System.in;
// 字节流转字符流
InputStreamReader isr = new InputStreamReader(is);
BufferedReader reader = new BufferedReader(isr);

OutputStream os = System.out;
// 字符流转字节流
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter writer = new BufferedWriter(osw);
*/
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));

String line = null;
while ((line = reader.readLine()) != null) {
if (line.equals("over")) {
break;
}
writer.write(line.toUpperCase());
writer.newLine();
writer.flush();
}
}
}


字节流 - InputStream/OutputStream



字节流操作文件不需要缓冲,直接写入到了目的文件中
public class Test {
public static void main(String[] args) {
File file = new File("e:\\demo.txt");
try {
writeFile(file, "Android" + System.lineSeparator() + "Java");
readFile(file);
} catch (IOException e) {
e.printStackTrace();
}
}

private static void readFile(File file) throws IOException {
FileInputStream fis = new FileInputStream(file);

byte[] buf = new byte[1024];
int len = 0;
while ((len = fis.read(buf)) != -1) {
System.out.println(new String(buf, 0, len));
}

/* 尽量少用available(),文件过大容易造成内存溢出
byte[] buf = new byte[fis.available()];
fis.read(buf);
System.out.println(new String(buf));
*/

fis.close();
}

private static void writeFile(File file, String in) throws IOException {
FileOutputStream fos = new FileOutputStream(file);
fos.write(in.getBytes());
fos.close();
}
}

使用字节流拷贝图片
public class Test {
public static void main(String[] args) {
try {
copyPic_1();
copyPic_2();
copyPic_3();
copyPic_4();
} catch (IOException e) {
e.printStackTrace();
}
}

private static void copyPic_1() throws IOException {
FileInputStream fis = new FileInputStream(new File("e:\\pic.jpg"));
FileOutputStream fos = new FileOutputStream(new File("e:\\pic_1.jpg"));

byte[] buf = new byte[1024];
int len = 0;
while ((len = fis.read(buf)) != -1) {
fos.write(buf, 0, len);
}
fos.close();
fis.close();
}

// 不建议使用,available()会影响性能
private static void copyPic_2() throws IOException {
FileInputStream fis = new FileInputStream(new File("e:\\pic.jpg"));
FileOutputStream fos = new FileOutputStream(new File("e:\\pic_2.jpg"));

byte[] buf = new byte[fis.available()];
fis.read(buf);
fos.write(buf);

fos.close();
fis.close();
}

// 不会使用,毫无效率,慢得不行!
private static void copyPic_3() throws IOException {
FileInputStream fis = new FileInputStream(new File("e:\\pic.jpg"));
FileOutputStream fos = new FileOutputStream(new File("e:\\pic_3.jpg"));

int ch = 0;
while ((ch = fis.read()) != -1) {
fos.write(ch);
}
fos.close();
fis.close();
}

private static void copyPic_4() throws IOException {
FileInputStream fis = new FileInputStream(new File("e:\\pic.jpg"));
BufferedInputStream bufis = new BufferedInputStream(fis);

FileOutputStream fos = new FileOutputStream(new File("e:\\pic_4.jpg"));
BufferedOutputStream bufos = new BufferedOutputStream(fos);

int ch = 0;
while ((ch = bufis.read()) != -1) {
bufos.write(ch);
}
bufis.close();
bufos.close();
}
}

键盘录入 - System.in
public class Test {
public static void main(String[] args) {
try {
readFromKeyboard();
} catch (IOException e) {
e.printStackTrace();
}
}

private static void readFromKeyboard() throws IOException {
InputStream is = System.in;
StringBuilder sb = new StringBuilder();

int ch = 0;
// read()是阻塞方法
while ((ch = is.read()) != -1) {
if (ch == '\r') {
continue;
}
if (ch == '\n') {
String tmp = sb.toString();
if (tmp.equals("over")) {
break;
}
System.out.println(tmp.toUpperCase());
sb.delete(0, sb.length());
} else {
sb.append((char) ch);
}
}
//从System.in获取的流对象只有一个,不需要关闭流,该流会随系统自动关闭
//关闭了就很难获取到
//is.close();
}
}

对象的序列化与反序列化 - ObjectInputStream/ObjectOutputStream
通过在流中使用文件可以实现对象的持久存储

ObjectOutputStream:将 Java 对象的基本数据类型和图形写入 OutputStream,即将对象写入文件中

ObjectInputStream:对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化,即从文件中读取对象

public class Test {
public static void main(String[] args) throws IOException, ClassNotFoundException {
File file = new File("e:\\person.object");

writeObj(new Person("zhangsan", 23, 1000, "xiaozhang"), file);
readObj(file);
}

// 保存对象到硬盘上,保存的对象需要序列化
private static void writeObj(Person person, File file) throws IOException {
ObjectOutputStream oop = new ObjectOutputStream(new FileOutputStream(file));
// 对象序列话。被序列话的对象必须实现Serializable接口
oop.writeObject(person);
oop.close();
}

private static void readObj(File file) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
// 对象的反序列化
Person person = (Person) ois.readObject();

System.out.println(person.name + " : " + person.age + " : " + person.money + " : "
+ person.nike);

ois.close();
}
}

/**
* Serializable:用于给被序列号的类加入ID号,用于判断类和对象是否是同一版本
*/
class Person implements Serializable /** 标记接口 */
{
// 通过该ID 判断对象和类是否是同一版本
private static final long serialVersionUID = 2L;

public String name;
public int age;

// static 不能被序列化保存到硬盘上,因为static不属于对象
public static int money;

// transient:非static的,不被序列化可以使用该关键字
public transient String nike;

public Person(String name, int age, int money, String nike) {
this.name = name;
this.age = age;
this.money = money;
this.nike = nike;
}
}

管道流 - PipedInputStream/PipedOutputStream
输入输出可以直接进行连接,通过结合线程使用

不建议对这两个对象尝试使用单个线程,因为这样可能会造成该线程死锁

public class Test {
public static void main(String[] args) throws IOException {
PipedInputStream input = new PipedInputStream();
PipedOutputStream output = new PipedOutputStream();

input.connect(output); // 关联起来
// PipedOutputStream output = new PipedOutputStream(input); //关联起来

new Thread(new Input(input)).start();
new Thread(new Out(output)).start();
}

}

class Input implements Runnable {
private PipedInputStream in;

public Input(PipedInputStream in) {
this.in = in;
}

public void run() {
try {
byte[] buf = new byte[1024];
int len = in.read(buf);
String s = new String(buf, 0, len);
System.out.println("s:" + s);
in.close();
} catch (Exception e) {
// TODO: handle exception
}
}
}

class Out implements Runnable {
private PipedOutputStream out;

public Out(PipedOutputStream out) {
this.out = out;
}

public void run() {
try {
out.write("PipedOutputStream ...".getBytes());
out.close();
} catch (Exception e) {
// TODO: handle exception
}
}
}

// 输出:
// s:PipedOutputStream ...

操作基本数据类型 - DataInputStream/DataOutputStream
应用程序可以使用数据输出流写入稍后由数据输入流读取的数据

DataInputStream 对于多线程访问不一定是安全的

public class Test {
public static void main(String[] args) throws IOException {
File file = new File("e:\\data.txt");
writeData(file);
readData(file);
}

private static void writeData(File file) throws IOException {
DataOutputStream dos = new DataOutputStream(new FileOutputStream(file));
dos.writeUTF("Hello DataOutputStream");
dos.close();
}

private static void readData(File file) throws IOException {
DataInputStream dis = new DataInputStream(new FileInputStream(file));
String utf = dis.readUTF();
System.out.println(utf);
}
}

// 输出:
// Hello DataOutputStream

操作字节数组 - ByteArrayInputStream/ByteArrayOutputStream
ByteArrayInputStream 包含一个内部缓冲区,该缓冲区包含从流中读取的字节

关闭 ByteArrayInputStream 无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何 IOException(因为该对象并没有操作底层资源)

public class Test {
public static void main(String[] args) throws IOException {
ByteArrayInputStream bis = new ByteArrayInputStream("ByteArrayInputStream".getBytes());
ByteArrayOutputStream bos = new ByteArrayOutputStream();

int ch = 0;

while ((ch = bis.read()) != -1) {
bos.write(ch);
}

System.out.println(bos.toString());
}

}

// 输出:
// ByteArrayInputStream


随机访问文件 - RandomAccessFile

支持对随机访问文件的读取和写入
1.随机访问文件,自身具备读写的方法
2.通过skipBytes(int x),seek(int x)来达到随机访问

特点
1. 该对象既能读,又能写
2. 该对象内部维护了一个byte数组,并通过指针可以操作数组中的元素
3. 可以通过getFilePointer方法获取指针的位置,和通过seek方法设置指针的位置
4. 该对象就是字节输入流和输出流进行了封装
5. 该对象的源或者目的只能是文件。通过构造函数可以看出

public class Test {
public static void main(String[] args) throws IOException {
File file = new File("e:\\random.txt");
writeFile(file);
randomWrite(file);
randomRead(file);
}

private static void writeFile(File file) throws IOException {
// 如果文件不存在,则创建;如果文件存在,则不创建
RandomAccessFile raf = new RandomAccessFile(file, "rw");
raf.write("zhangsan".getBytes());
raf.writeInt(22);

raf.write("lisi".getBytes());
raf.writeInt(25);

raf.close();
}

private static void randomWrite(File file) throws IOException {
// 如果文件不存在,则创建;如果文件存在,则不创建
RandomAccessFile raf = new RandomAccessFile(file, "rw");

raf.seek(12); // 随机写入,只要指定指针的位置即可
raf.write("wangwu".getBytes());
raf.writeInt(25);

raf.close();
}

// 可以用于多线程写入
private static void randomRead(File file) throws IOException {
RandomAccessFile raf = new RandomAccessFile(file, "r");
// 通过seek设置指针位置
raf.seek(12); // 随机读取,只要指定指针的位置即可

byte[] buf = new byte[6];
raf.read(buf);

System.out.println("name:" + new String(buf) + " age:" + raf.readInt());
raf.close();
}
}

// 输出:
// name:wangwu age:25


异常处理 - IOException

public class Test {
// 换行
private static final String LINE_SEPARATOR = System.lineSeparator();

public static void main(String[] args) {
File file = new File("h:\\fileWriter.txt");
writeFile(file, "FileWriter");
}

private static void writeFile(File path, String input) {
FileWriter writer = null;
try {
writer = new FileWriter(path);
writer.append(input + LINE_SEPARATOR);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (writer != null)
writer.close();
} catch (IOException e) {
throw new RuntimeException("Close fail!");
}
}
}
}

// java.io.FileNotFoundException


编码

常见编码表
ASCII:美国标准信息交换吗  =>用一个字节的7位可以表示

ISO8859-1:拉丁码表。欧洲码表 =>用一个字节的8位表示

GB2312:中国的中文编码表
GBK:中国的中文编码表升级

Unicode:国际标准码,融合了多种文字。 =>所有文字都用两个字节来表示,java语言使用的就是unicode

UTF-8:最多用三个字节来表示一个字符

字符串-->字节数组:编码
字节数组-->字符串:解码

public class Test {
public static void main(String[] args) throws IOException {
String str = "你好";
// 编码
byte[] buf_gbk = str.getBytes("GBK");
byte[] buf_utf = str.getBytes("utf-8");

// 解码
printBytes(buf_gbk);
printBytes(buf_utf);
}

private static void printBytes(byte[] buf) {
for (byte b : buf) {
System.out.print(b + " ");
}
System.out.println();
}

}

// 输出:
// -60 -29 -70 -61
// -28 -67 -96 -27 -91 -67


流的基本操作规律

转换流
InputStreamReader:字节流到字符流的桥梁。解码。
OutputStreamWriter:字符到字节的桥梁。编码。

流的操作规律
1、明确源和目的
源:InputStream Reader
目的:OutputStream Writer

2、明确数据是否是纯文本数据
源:是纯文本:Reader
否:InputStream
目的:是纯文本:Writer
否:OutputStream

3、明确具体的设备
源设备:
硬盘:File
键盘:System.in
内存:数组
网络:Socket流
目的设备:
硬盘:File
控制台:System.out
内存:数组
网络:Socket流

4、是否需要其他额外功能
是否需要高效(缓冲区):是,就加上Buffer
是否需要转换:是...

什么时候使用转换流?
1. 源或者目的对应的设备是字节流,但是操作的却是文本数据,可以使用转换流作为桥梁。提高对文本操作的便捷。
2. 一旦操作文本涉及到具体的指定的编码表时,必须使用转换流。

转换流的编码解码
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("gbk.txt"), "gbk");
FileWriter fw = new FileWriter("gbk.txt");
//这两句代码功能是相同的

FileWriter其实就是转换流指定了本地默认码表的体现。而且是这个转换流的子类对象,可以方便操作文本文件

简单说:操作文件的字节流+本机默认的编码表,这是按照默认码表来操作文件的便捷类

如果操作文本文件需要明确具体的编码,FileWriter就不行了,必须用转换流

注意:如果明确指定了编码表的动作,那就不可以使用FileWriter,因为FileWriter内部是使用默认的本地码表,只能使用其父类OutputStreamWriter。
OutputStreamWriter接收一个字节流对象,既然是操作文件,那么该对象应该是FileOutputStream

public class Test {
public static void main(String[] args) {
File file = new File("e:\\demo.txt");
try {
writeFile(file, "你好" + System.lineSeparator() + "安卓", "utf-8");
readFile(file, "gbk");
readFile(file, "utf-8");
} catch (IOException e) {
e.printStackTrace();
}
}

private static void readFile(File file, String code) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file),
code));
String line = null;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
reader.close();
}

private static void writeFile(File file, String in, String code) throws IOException {
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(file), code));
writer.write(in);
writer.close();
}
}

/**输出:
浣犲ソ
瀹夊崜
你好
安卓
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: