一、文件的编码

 package com.study.io;

 /**
* 测试文件编码
*/
public class EncodeDemo { /**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
String s="好好学习ABC";
byte[] bytes1=s.getBytes();//这是把字符串转换成字符数组,转换成的字节序列用的是项目默认的编码(这里为UTF-8)
for (byte b : bytes1) {
//把字节(转换成了int)以16进制的方式显示
System.out.print(Integer.toHexString(b & 0xff)+" ");//& 0xff是为了把前面的24个0去掉只留下后八位
}
System.out.println();
/*utf-8编码中中文占用3个字节,英文占用1个字节*/
byte[] bytes2 = s.getBytes("utf-8");//这里会有异常展示,我们就throw这个异常
for (byte b : bytes2) {
System.out.print(Integer.toHexString(b & 0xff)+" ");
}
System.out.println();
/*gbk编码中文占用2个字节,英文占用1个字节*/
byte[] bytes3 = s.getBytes("gbk");//这里会有异常展示,我们就throw这个异常
for (byte b : bytes3) {
System.out.print(Integer.toHexString(b & 0xff)+" ");
} System.out.println();
/*utf-16be编码中文占用2个字节,英文占用2个字节*/
byte[] bytes4 = s.getBytes("utf-16be");//这里会有异常展示,我们就throw这个异常
for (byte b : bytes4) {
System.out.print(Integer.toHexString(b & 0xff)+" ");
} System.out.println();
/*当你的字节序列是某种编码时,这个时候想把字节序列变成字符串,也需要用这种编码方式,否则会出现乱码*/
String str1=new String(bytes4);//这时会使用项目默认的编码来转换,可能出现乱码
System.out.println(str1);
//要使用字节序列的编码来进行转换
String str2=new String(bytes4,"utf-16be");
System.out.println(str2);
}
}

分析:

* 1. “& 0xff”的解释:
* 0xFF表示的是16进制(十进制是255),表示为二进制就是“11111111”。
* 那么&符表示的是按位数进行与(同为1的时候返回1,否则返回0)

* 2.字节byte与int类型转换:
* Integer.toHexString(b & 0xff)这里先把byte类型的b和0xff进行了运算,然后Integer.toHexString取得了十六进制字符串
* 可以看出b & 0xFF运算后得出的仍然是个int,那么为何要和 0xFF进行与运算呢?直接 Integer.toHexString(b);,将byte强转为int不行吗?答案是不行的.
* 其原因在于:1.byte的大小为8bits而int的大小为32bits;2.java的二进制采用的是补码形式
* Integer.toHexString的参数是int,如果不进行&0xff,那么当一个byte会转换成int时,由于int是32位,而byte只有8位这时会进行补位。。。。。。
* 所以,一个byte跟0xff相与会先将那个byte转化成整形运算,这样,结果中的高的24个比特就总会被清0,于是结果总是我们想要的。

* 3.utf-8编码:中文占用3个字节,英文占用1个字节
* gbk编码:中文占用2个字节,英文占用1个字节
* Java采用双字节编码(就是Java中的一个字符占两个字节)是utf-16be编码。中文占用2个字节,英文占用2个字节
*
* 4.当你的字节序列是某种编码时,这个时候想把字节序列变成字符串,也需要用这种编码方式,否则会出现乱码

* 5.文本文件 就是字节序列。可以是任意编码的字节序列。
* 如果我们在中文机器上直接创建文本文件,那么该文件只认识ANSI编码(例如直接在电脑中创建文本文件)

二、File类的使用

 package com.study.io;

 import java.io.File;

 /**
* File类的使用
*/
public class FileDemo {
/*java.iO.File类表示文件或目录
File类只用于表示文件或目录的信息(名称,大小等),不能用于文件内容的访问。*/
public static void main(String[] args) {
File file=new File("D:\\111");//创建文件对象时指定目录需要用双斜杠,因为“\”是转义字符
/*目录的中间的分隔符可以用双斜杠,也可以用反斜杠,也可以用File.separator设置分隔符*/
// File file1=new File("d:"+File.separator);
// System.out.println(file.exists());//exists()判断文件或文件夹是否存在
if(!file.exists()){//如果文件不存在
file.mkdir();//创建文件夹mkdir(),还有mkdirs()创建多级目录
}else{
file.delete();//删除文件或文件夹
}
//判断是否是一个目录isDirectory,如果是目录返回true,如果不是目录或者目录不存在返回false
System.out.println(file.isDirectory());
//判断是否是一个文件isFile
System.out.println(file.isFile()); File file2=new File("D:\\222","123.txt");
//常用API:
System.out.println(file);//打印的是file.toString()的内容
System.out.println(file.getAbsolutePath());//获取绝对路径
System.out.println(file.getName());//获取文件名称
System.out.println(file2.getName());
System.out.println(file.getParent());//获取父级绝对路径
System.out.println(file2.getParentFile().getAbsolutePath());
}
}

运行结果:

说明:

java.iO.File类表示文件或目录
File类只用于表示文件或目录的信息(名称,大小等),不能用于文件内容的访问。
常用的API:
1.创建File对象:File file=new File(String path);注意:File.seperater();获取系统分隔符,如:“\”.
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();获取父级绝对路径。

❤❤1、遍历目录

 package com.study.io;

 import java.io.File;
import java.io.IOException; /**
* File工具类
* 列出File类的常用操作,比如:过滤、遍历等操作
*/
public class FileUtils {
/**
* 列出指定目录下(包括其子目录)的所有文件
* @param dir
* @throws IOException
*/
public static void listDirectory(File dir) throws IOException{
if(!dir.exists()){//exists()方法用于判断文件或目录是否存在
throw new IllegalArgumentException("目录:"+dir+"不存在");
}
if(!dir.isDirectory()){//isDirectory()方法用于判断File类的对象是否是目录
throw new IllegalArgumentException(dir+"不是目录");
}
/*String[] fileNames = dir.list();//list()方法用于列出当前目录下的子目录和文件(直接是子目录的名称,不包含子目录下的内容),返回的是字符串数组
for (String string : fileNames) {
System.out.println(string);
}*/ //如果要遍历子目录下的内容就需要构造成File对象做递归操作,File提供了直接返回File对象的API
File[] listFiles = dir.listFiles();//返回的是直接子目录(文件)的抽象
if(listFiles !=null && listFiles.length >0){
for (File file : listFiles) {
/*System.out.println(file);*/
if(file.isDirectory()){
//递归
listDirectory(file);
}else{
System.out.println(file);
}
}
}
}
}

测试类:

 public class FileUtilsTest1 {
public static void main(String[] args) throws IOException {
FileUtils.listDirectory(new File("D:\\ioStudy"));
}
}

运行结果:

三、RandomAccessFile类的使用

RandomAccessFile:java提供的对文件内容的访问,既可以读文件,也可以写文件。
RandomAccessFile支持随机访问文件,可以访问文件的任意位置。

注意 Java文件的模型:

示例代码:

 package com.study.io;

 import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Arrays; /**
* RandomAccessFile
*/
public class RandomAccessFileDemo {
public static void main(String[] args) throws IOException{
File demo = new File("demo");
if(!demo.exists()){
demo.mkdir();
}
File file = new File(demo,"raf.dat");
if(!file.exists()){
file.createNewFile();
} RandomAccessFile raf = new RandomAccessFile(file, "rw");
//指针的位置
System.out.println(raf.getFilePointer()); raf.write('A');//只写了一个字节
System.out.println(raf.getFilePointer());
raf.write('B'); int i = 0x7fffffff;
//用write方法每次只能写一个字节,如果要把i写进去就得写4次
raf.write(i >>> 24);//高8位
raf.write(i >>> 16);
raf.write(i >>> 8);
raf.write(i);
System.out.println(raf.getFilePointer()); //可以直接写一个int
raf.writeInt(i); String s = "中";
byte[] gbk = s.getBytes("gbk");
raf.write(gbk);
System.out.println(raf.length()); //读文件,必须把指针移到头部
raf.seek(0);
//一次性读取,把文件中的内容都读到字节数组中
byte[] buf = new byte[(int)raf.length()];
raf.read(buf); System.out.println(Arrays.toString(buf));
for (byte b : buf) {
System.out.println(Integer.toHexString(b & 0xff)+" ");
}
raf.close();
}
}

运行结果:

0
1
6
12
[65, 66, 127, -1, -1, -1, 127, -1, -1, -1, -42, -48]
41
42
7f
ff
ff
ff
7f
ff
ff
ff
d6
d0

四、字节流(InputStream、OutputStream)

Java流操作有关的类或接口:

Java流类图结构:

IO流的分类

  • 根据处理数据类型的不同分为:字符流和字节流
  • 根据数据流向不同分为:输入流和输出流

字符流和字节流

字符流的由来: 因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表。 字节流和字符流的区别:

  • 读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
  • 处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。

结论:只要是处理纯文本数据,就优先考虑使用字符流。 除此之外都使用字节流。

输入流和输出流

对输入流只能进行读操作,对输出流只能进行写操作,程序中需要根据待传输数据的不同特性而使用不同的流。

代码示例:

 package com.study.io;

 import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException; /**
* IO工具类
* ❤文件输入输出流:
* FileInputStream-->具体实现了在文件上读取数据
* FileOutputStream-->实现了向文件中写出byte数据的方法
* ❤数据输入输出流:
* DataOutputStream / DataInputStream:对"流"功能的扩展,可以更加方面的读取int,long,字符等类型数据
* DataOutputStream writeInt()/writeDouble()/writeUTF()
* ❤字节缓冲流:
* BufferedInputStream & BufferedOutputStream
* 这两个流类位IO提供了带缓冲区的操作,一般打开文件进行写入或读取操作时,都会加上缓冲,这种流模式提高了IO的性能
* 比如:从应用程序中把输入放入文件,相当于将一缸水倒入到另一个缸中:
FileOutputStream--->write()方法相当于一滴一滴地把水“转移”过去
DataOutputStream-->writeXxx()方法会方便一些,相当于一瓢一瓢把水“转移”过去
BufferedOutputStream--->write方法更方便,相当于一瓢一瓢先放入桶中(即缓存区),再从桶中倒入到另一个缸中,性能提高了
*/
public class IOUtil { /**
* 读取指定文件内容,按照16进制输出到控制台
* 并且每输出10个byte换行
* @param fileName
* 单字节读取不适合大文件,大文件效率很低
*/
public static void printHex(String fileName)throws IOException{
//把文件作为字节流进行都操作
FileInputStream in=new FileInputStream(fileName);
int b;
int i=1;
while((b=in.read())!=-1){
/* 0xff换成2进制就是8个1,这样与的话,其实就是取到了字符的低8位。
* oxf就是15, 小于15的数会转换成一个16进制数,
* 你的代码里希望是固定的两个16进制数,所以当只会产生一个时要加个0*/
if(b <= 0xf){
//单位数前面补0
System.out.print("0");
}
//Integer.toHexString(b)将整型b转换为16进制表示的字符串
System.out.print(Integer.toHexString(b)+" ");
if(i++%10==0){
System.out.println();
}
}
in.close();//文件读写完成以后一定要关闭
} /**
* 批量读取,对大文件而言效率高,也是我们最常用的读文件的方式
* @param fileName
* @throws IOException
*/
public static void printHexByByteArray(String fileName)throws IOException{
FileInputStream in = new FileInputStream(fileName);
byte[] buf = new byte[8 * 1024];
/*从in中批量读取字节,放入到buf这个字节数组中,
* 从第0个位置开始放,最多放buf.length个
* 返回的是读到的字节的个数
*/
/*int bytes = in.read(buf,0,buf.length);//一次性读完,说明字节数组足够大
int j = 1;
for(int i = 0; i < bytes;i++){
System.out.print(Integer.toHexString(buf[i] & 0xff)+" ");
if(j++%10==0){
System.out.println();
}
}*/
int bytes = 0;
int j = 1;
while((bytes = in.read(buf,0,buf.length))!=-1){
for(int i = 0 ; i < bytes;i++){
System.out.print(Integer.toHexString(buf[i] & 0xff)+" ");
/**
* & 0xff:byte类型8位,int类型32位,为了避免数据转换错误,通过&0xff将高24位清零
*/
if(j++%10==0){
System.out.println();
}
}
}
in.close();
} /**
* 文件拷贝,字节批量读取
* @param srcFile
* @param destFile
* @throws IOException
*/
public static void copyFile(File srcFile, File destFile) throws IOException {
if (!srcFile.exists()) {
throw new IllegalArgumentException("文件:" + srcFile + "不存在");
}
if (!srcFile.isFile()) {
throw new IllegalArgumentException(srcFile + "不是文件");
}
FileInputStream in = new FileInputStream(srcFile);
FileOutputStream out = new FileOutputStream(destFile);//文件不存在时,会直接创建;如果存在,删除后建
byte[] buf = new byte[8 * 1024];//批量读写
int b;
while ((b = in.read(buf, 0, buf.length)) != -1) {//read(buf,0,buf.length)带参数的read返回的是字节的总长度;当全部读完后返回的是-1;
out.write(buf, 0, b);
out.flush();// 最好加上
}
in.close();
out.close();
} /**
* 进行文件的拷贝,利用带缓冲的字节流
* @param srcFile
* @param destFile
* @throws IOException
*/
public static void copyFileByBuffer(File srcFile,File destFile)throws IOException{
if(!srcFile.exists()){
throw new IllegalArgumentException("文件:"+srcFile+"不存在");
}
if(!srcFile.isFile()){
throw new IllegalArgumentException(srcFile+"不是文件");
}
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));
int c ;
while((c = bis.read())!=-1){
bos.write(c);
bos.flush();//刷新缓冲区
}
bis.close();
bos.close();
} /**
* 单字节,不带缓冲进行文件拷贝
* @param srcFile
* @param destFile
* @throws IOException
*/
public static void copyFileByByte(File srcFile,File destFile)throws IOException{
if(!srcFile.exists()){
throw new IllegalArgumentException("文件:"+srcFile+"不存在");
}
if(!srcFile.isFile()){
throw new IllegalArgumentException(srcFile+"不是文件");
}
FileInputStream in = new FileInputStream(srcFile);
FileOutputStream out = new FileOutputStream(destFile);
int c ;
while((c = in.read())!=-1){//read()不带参数的read返回的是读到的字节内容;当全部读完后返回的都是是-1;
out.write(c);
out.flush();
}
in.close();
out.close();
}
}

测试类:

package com.study.io;

import java.io.File;
import java.io.IOException; import org.junit.Test; public class IOUtilTest { @Test
public void testPrintHex() {
try {
IOUtil.printHex("D:\\Javaio\\FileUtils.java");
} catch (IOException e) {
e.printStackTrace();
}
} @Test
public void testPrintHexByByteArray() {
try {
long start = System.currentTimeMillis();//当前时间与协调世界时 1970 年 1 月 1 日午夜之间的时间差(以毫秒为单位测量)
//IOUtil.printHexByByteArray("e:\\javaio\\FileUtils.java");
//IOUtil.printHex("e:\\javaio\\1.mp3");
IOUtil.printHexByByteArray("e:\\javaio\\1.mp3");
System.out.println();
long end = System.currentTimeMillis();
System.out.println(end - start);
} catch (IOException e) {
e.printStackTrace();
}
} @Test
public void testCopyFile(){
try {
IOUtil.copyFile(new File("d:\\javaio\\1.txt"), new File("d:\\javaio\\1copy.txt"));
} catch (IOException e) {
e.printStackTrace();
}
} @Test
public void testCopyFileByBuffer(){
try {
long start = System.currentTimeMillis();
/*IOUtil.copyFileByByte(new File("e:\\javaio\\1.mp3"), new File(
"e:\\javaio\\2.mp3"));*/ //两万多毫秒
/*IOUtil.copyFileByBuffer(new File("e:\\javaio\\1.mp3"), new File(
"e:\\javaio\\3.mp3"));//一万多毫秒*/
IOUtil.copyFile(new File("e:\\javaio\\1.mp3"), new File(
"e:\\javaio\\4.mp3"));//7毫秒
long end = System.currentTimeMillis();
System.out.println(end - start );
} catch (IOException e) {
e.printStackTrace();
}
}
}

五、字符流(Reader、Writer)

 package com.study.io;

 import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter; public class IsrAndOswDemo {
public static void main(String[] args)throws IOException {
FileInputStream in = new FileInputStream("e:\\javaio\\utf8.txt");
InputStreamReader isr = new InputStreamReader(in,"utf-8");//默认项目的编码,操作的时候,要写文件本身的编码格式 FileOutputStream out = new FileOutputStream("e:\\javaio\\utf81.txt");
OutputStreamWriter osw = new OutputStreamWriter(out,"utf-8");
/*int c ;
while((c = isr.read())!=-1){
System.out.print((char)c);
}*/
char[] buffer = new char[8*1024];
int c;
/*批量读取,放入buffer这个字符数组,从第0个位置开始放置,最多放buffer.length个返回的是读到的字符的个数*/
while(( c = isr.read(buffer,0,buffer.length))!=-1){
String s = new String(buffer,0,c);
System.out.print(s);
osw.write(buffer,0,c);
osw.flush();
}
isr.close();
osw.close(); } }

❤ 字符流之文件读写流(FileReader/FileWriter) 

❤ 字符流的过滤器

六、对象的序列化和反序列化

示例:

注意:

序列化拓展文章:

深入分析Java的序列化与反序列化

Java 序列化的高级认识(转载)

文件传输基础——Java IO流的更多相关文章

  1. 慕课网_文件传输基础——Java IO流

    第1章 文件的编码 1-1 文件的编码 (15:07) 第2章 File 类的使用 2-1 File 类常用 API 介绍 (10:50) import java.io.File; import ja ...

  2. 文件传输基础----Java IO流

    编码问题 一个很著名的奇怪现象:当你在 windows 的记事本里新建一个文件,输入"联通"两个字之后,保存,关闭,然后再次打开,你会发现这两个字已经消失了,代之的是几个乱码!呵呵 ...

  3. Java IO流详解(二)——File类

    在上一章博客中简单的介绍了Java IO流的一些特征.也就是对文件的输入输出,既然至始至终都离不开文件,所以Java IO流的使用得从File这个类讲起. File类的描述:File类是文件和目录路径 ...

  4. Java:IO流与文件基础

    Java:IO流与文件基础 说明: 本章内容将会持续更新,大家可以关注一下并给我提供建议,谢谢啦. 走进流 什么是流 流:从源到目的地的字节的有序序列. 在Java中,可以从其中读取一个字节序列的对象 ...

  5. 【Java基础】Java IO流的总结

    Java IO流分为输入流和输出流,而输入流和输出流中又分字符流和字节流.顾名思义,输入流则是输入到程序中计算,输出流是把程序的结果输出到文件或者设备.而字符流输入输出以字符为单位,字节流则是以字节为 ...

  6. java基础之 IO流

    javaIO流   IO流 : (input  output) 输入输出流 :输入 :将文件读到内存中 输出:将文件从内存输出到其他地方.   IO技术的作用:主要就是解决设备和设备之间的数据传输问题 ...

  7. java基础06 IO流

    IO用于在设备间进行数据传输的操作. Java IO流类图结构:   IO流分类 字节流: InputStream FileInputStream BufferedInputStream Output ...

  8. Java基础之IO流学习总结

    Java流操作有关的类或接口: Java流类图结构: 流的概念和作用 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象.即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输 ...

  9. java基础之io流总结一:io流概述

    IO流概念: 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象.io流是实现输入和输出的基础,可以方便的实现数据的输入和输出操作. IO流的分类: 根据处理数据类型的不同分为:字符流 ...

随机推荐

  1. 将组策略中的内容导出至CSV格式

    #将组策略首选项中的"本地用户和组"下的所有条目导出 $xml = Get-GPOReport -ReportType Xml -Name "China Desktop ...

  2. Asp.Net:Repeater 详情 备用

    页面 repeator就想for循环一样,没有编辑模板,有删除delete和详情detail模板 <%@ Page Language="C#" AutoEventWireup ...

  3. Bungie Interview with Halo3 Developer

    http://www.realtimerendering.com/blog/tag/bungie/ Digital Foundry interview with Halo: Reach develop ...

  4. java web基础2HTTP协议知识点总结

    一.HTTP协议基础 1.定义:HTTP是基于TCP连接的浏览器与服务器通信协议.(即传输层先用TCP三次握手建立连接,进而HTTP通信) 2.连接原理:先进行TCP建立端到端连接,然后发送和接受HT ...

  5. Python装饰器与面向切面编程

    今天来讨论一下装饰器.装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数 ...

  6. DNS:www.flickr.com

    203.84.197.9 203.84.197.25 203.84.197.26 203.84.197.27

  7. PHP Error 和 Logging 函数

    PHP Error 和 Logging 函数 PHP Error 和 Logging 简介 Error 和 Logging 函数允许您对错误进行处理和记录. Error 函数允许用户定义错误处理规则, ...

  8. 【IOS笔记】Views

    Views Because view objects are the main way your application interacts with the user, they have many ...

  9. 使用photoshop,把图片背景变成透明

    鄙人使用的是photoshop CS6,win7系统,好了废话不多说,我们开始吧 1.打开photoshop,选择一个要编辑的图片 2.在右下角的图层面板上用鼠标左键快速双击背景图层为图片解锁 3.在 ...

  10. 微博app中常用正则表达式

    /* weibo.app 里面的正则,有兴趣的可以参考下: HTTP链接 (例如 http://www.weibo.com ): ([hH]ttp[s]{0,1})://[a-zA-Z0-9\.\-] ...