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

Java基础(20,21)IO流

2015-04-06 10:45 381 查看

二十八.IO流列出目录下所有内容-递归

import java.io.*;
class IoTextDemo
{
public static void main(String[] args)
{
//开始名字写错了,返回null
File dir = new File("E:\\JAVA_TEXT"); //System.out.println(dir);//打印的是E:\\JAVA_TEST

//System.out.println(dir);
showDir(dir,0);
}
public static String getLevel(int level)
{
StringBuilder sb = new StringBuilder();

sb.append("|--");
for(int i = 0;i<level;i++)
{
sb.insert(0 ,"|  ");
}
return sb.toString();

}

public static void showDir(File dir,int level)
{

System.out.println(getLevel(level)+dir.getName());
level++;

File[] filelist =dir.listFiles();

//System.out.println(dir);//显示主目录的名字
for(int i = 0;i<filelist.length;i++)
{

if(filelist[i].isDirectory())//如果读到的是一个目录,就继续往里面读
{
showDir(filelist[i],level);
}
else //不是目录是文件
{

System.out.println(filelist[i]);//这个地方不写层级,
//只有目录会有| ,文件前面没有
//System.out.println(getLevel(level)+filelist[i]);
}

}

}
}


二十九.IO流删除带内容的目录

删除原理:

在window中,删除目录从里面往外删除的。

既然从里往外删除。就需要用到递归

import java.io.*;

class IoTextDemo
{
public static void main(String[] args)
{
File dir = new File("E:\\JAVA_TEXT");

removeDir(dir);

}

public static void removeDir(File dir)
{
File[] files = dir.listFiles();

for(int i = 0;i<files.length;i++)
{
if(files[i].isDirectory())
{

removeDir(files[i]);//如果是目录继续往里走,看看是不是目录,知道找到文件然后删除
}
else
{
//如果打印false ,就说明一个文件夹被删了两次
System.out.println(files[i].toString()+"-file-"+files[i].delete());
}
}

System.out.println(dir+"::"+dir.delete());//删除文件

}
}

三十.IO流创建java文件列表,   前面有一个用listFile做的,可以对比一下

练习

将一个指定目录下的java文件的绝对路径,存储到一个文本文件中。

建立一个Java文件列表文件。

思路:

1.对指定的目录进行递归。

2.获取递归过程所有的java文件的路径

3.将这些路径存储到集合中,存入list!!!!

4.将集合中的数据写入到一个文件中

import java.io.*;
import java.util.*;
class IoTextDemo
{
public static void main(String[] args)
{
File dir = new File("E:\\JAVA_TEXT");
//FileWriter fw = new FileWriter("E:\\list_document.txt");
File f = new File("E:\\list_java.txt");//看看f打印什么
File f1 = new File("E:\\玩玩.txt");
try
{
System.out.println(f);  //打印出E:\list_java.txt   //这个文件存在
System.out.println(f1); //打印出E:\玩玩.txt  //这个文件并不存在
}
catch (Throwable e)
{
throw new RuntimeException("cuo");
}

ArrayList<File> alist = new ArrayList<File>();

fileAddToList(dir,alist); //把文件信息存到集合中

writeTofile(alist ,f.toString());  //从集合中把信息写到文件上

}
public static void fileAddToList(File dir ,ArrayList<File> list )
{

File[] files = dir.listFiles();

//	高级for循环取数据
//	for(File file : files)
//	{
//		if(file.isDirectory())
//		{
//			fileToList(file ,list);
//		}
//		else
//		{
//			if(file.getName().endsWith(“.java”))
//			list.add(file);
//		}

//	}

//传统for循环
for(int i = 0;i<files.length;i++)
{
if(files[i].isDirectory()) //如果是目录就继续进去
{
fileAddToList(files[i],list)	;
}
else //如果是文件就添加进list集合
{
if(files[i].getName().endsWith("java"))
list.add(files[i]);

}

}

}
public static void writeTofile(ArrayList<File> list , String file)
{

FileWriter fw = null;
BufferedWriter bufw = null;
try
{
fw = new FileWriter(file);
bufw = new BufferedWriter(fw);

//	高级for循环取出数据
//	for(File f:list)
//	{
//	String path = f.getAbsolutePath();
//	bufw.write(path);
//	bufw.newLine();
//	bufw.flush();
//	}

//用迭代器取出数据
Iterator<File> it = list.iterator();  //这里开始写错了
while(it.hasNext())
{
File fi = it.next();
String filepath = fi.getAbsolutePath();
bufw.write(filepath);
bufw.newLine();
bufw.flush();

}
}
catch (Throwable e)
{
throw new RuntimeException("错误1");
}
finally
{
try
{
if(bufw !=null)
{
bufw.close();
}
}
catch (Throwable e)
{
throw new RuntimeException("错误2");
}

}

}
}


三十一.IO流Properties

//properties是hashtable的子类

//也就是说它具备map集合的特点。而且它里面存储的键值对都是字符串。

//是集合中和IO技术相结合的结合容器。

//该对象的特点:可以用于键值对形式的配置文件。

//那么在加载数据时,需要数据有固定的格式,通常键 = 值。

import java.io.*;
import java.util.*;

class IoTextDemo
{
public static void main(String[] args) throws IOException
{

//setAndGet();
method_1();
}

public static void setAndGet()
{
Properties prop = new Properties();
//setProperty(String key, String value),调用Hashtable的put方法
prop.setProperty("zhangsan","30");
prop.setProperty("lisi","39");

System.out.println(prop);
//stringPropertyNames()返回此属性列表中的键集,
//其中该键及其对应值是字符串,如果在主属性列表中未找到同名的键,
//则还包括默认属性列表中不同的键。
String value = prop.getProperty("lisi");
System.out.println(value);

Set<String> names = prop.stringPropertyNames();

prop.setProperty("lisi",89+"");//改变元素的值//改变值
for(String  s : names)
{
System.out.println(s+":"+prop.getProperty(s)); //获取key
}

}

//代码2
//演示,如何将流中的数据存储到集合中。
//想要将info.txt中键值数据存到集合中进行操作。
//1.用一个流和info.txt文件关联。
//2.读取一行数据,将该行数据用”=”进行切割。
//3.等号左边作为键,右边作为值。存入到Properties集合中即可。
public static void method_1() throws IOException
{

BufferedReader bufr = new BufferedReader(new FileReader("E:\\SYSTEM_INFO.txt"));
String line = null;
Properties prop = new Properties();
while((line = bufr.readLine()) != null)
{
String[] arr = line.split("=");
System.out.println(arr[0]+"---"+arr[1]);
prop.setProperty(arr[0],arr[1]);

}
bufr.close();
System.out.println(prop);

}

///代码3(优化代码2)
public static void loadDemo() throws IOException //跟下面的功能一样,只是更简单了
{
Properties prop = new Properties();
FileInputStream fis = new FileInputStream(“info.txt”);
//将流中的数据加载进集合。从输入流中读取属性列表(键和元素对)。
prop.load(fis);
//System.out.println(prop);//和下面的效果一样 把键和值成对打印
//prop.list(System.out);//和上面的效果一样
//之前是99,这里改成39,打印出39,但是文件中还是99
prop.setProperty(“wangwu”,”39”); / /只是改变了内存中值,源头没改变,如果要改变需要存起来
//store是将内存中的数据(也就是上面的setProperty的数据)先存到流中,然后存到文件中,会打印时间
FileOutputStream  fos = new FileOutputStream(“info.txt”);
prop.store(fos.”haha”);//haha是注释

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


三十二.IO流Properties练习

//用于记录应用程序运行次数。

//如果使用次数已到,那么给出注册提示。

//很容易想到的是:计数器

//可是该计数器定义在程序中,随着程序的运行而在内存中存在,并自行自增

//可是随着该应用程序的退出,该计数器也在内存中消失了。

//下一次在启动该程序,又重新开始从0计数。

//这样不是我们想要的。

//程序即时结束,该计数器的值也存在。

//下次程序启动时会先加载该计数器的值并加1后再重新存储起来。

//所以要建立一个配置文件。用于记录该软件的使用次数。

//该配置文件使用键值对的形式。

//这样便于阅读数据,并操作数据。

//键值对数据是map集合

//数据是以文件形式存储,使用io技术

//那么map+io-->properties

//配置文件可以实现应用程序数据的共享

import java.io.*;
import java.util.*;
class IoTextDemo
{
public static void main(String[] args) throws IOException
{
File file = new File("E:\\count.txt");
Properties pro = new Properties();

if(!file.exists())
{

file.createNewFile(); //如果不存在就创建一个
}
FileInputStream fis = new FileInputStream(file);

pro.load(fis);
int count = 0;
String value = pro.getProperty("time");
if(value == null)
{

count++;
pro.setProperty("time",count+"");

}
else
{
count = Integer.parseInt(value); //如果没有这个,那么count每次进来都是0!!!
count ++;
pro.setProperty("time",count+"");
if(count >4)
{

System.out.println("到期,请续费");
}

}
FileOutputStream fos = new FileOutputStream(file); //改变了数据就要存到file文件中
pro.store(fos,"");
fos.close();
fis.close();

}
}

三十三.IO流printWriter

PrintWriter与PrintStream

可以直接操作输入流和文件

打印流:

该流提供了打印方法,可以将各种数据类型的数据都原样打印!!!

字节打印流:

PrintStream

构造函数可以接受的参数类型:

1.file对象。File

2.字符串路径。String

3.字节输出流。OutputStream(控制台对应的对象时是字节输出流)

字符打印流:

PrintWriter

构造函数可以接受的参数类型:

1file对象。File

2字符串路径。String

3字节输出流。OutputStream
4.字符输出流,Writer (跟上面的差别所在)

PrintWriter(OutputStream out , boolean auto Flush)

out - 输出流

autoFlush - boolean变量;如果为true ,则println,printf或format方法将刷新输出缓冲区

import java.io.*;

class IoTextDemo
{
public static void main(String[] args) throws IOException
{
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));

//控制台输出
//PrintWriter out = new PrintWriter(System.out , true);

//如果把输出写入一个文件时,不能写true,因为针对的是流,才能自动刷新
//PrintWriter out = new PrintWriter("E:\\20150405text2.txt");

//把写入文件也弄成自动刷新
//和上面的区别在于,输入完之后,不用over,文件就自动生成大写
PrintWriter out = new PrintWriter(new FileWriter("E:\\20150405text4.txt"),true);

String line = null;
while((line = bufr.readLine()) != null)
{
if("over".equals(line))
{
break;
}
//如果new PrintWriter(System.out , true);不写true,那么输入小写之后不会立即显示写,因为在缓冲区中
//没有刷新,over之后才会全部出来。如果有true,写一个对应的大写就出来了,自动刷新
out.println(line.toUpperCase());

}
out.close();
bufr.close();
}
}

三十四.IO合并流

//把三个流放一起,然后再写在一个文件里(分别读取三个文件存到一个,要考虑续写问题,多个源对应一个目的)

//这里直接把多个源,变成一个源

import java.io.*;
import java.util.*;

class IoTextDemo
{
public static void main(String[] args) throws IOException
{
Vector<FileInputStream> v = new Vector<FileInputStream>();
v.add(new FileInputStream("E:\\hebing\\1.txt"));
v.add(new FileInputStream("E:\\hebing\\2.txt"));
v.add(new FileInputStream("E:\\hebing\\3.txt"));

Enumeration<FileInputStream> en = v.elements();

//SequenceInputStream(Enumeration<? extends InputStream> e)
//通过记住参数来初始化新创建的 SequenceInputStream,
//该参数必须是生成运行时类型为 InputStream 对象的 Enumeration 型参数。
SequenceInputStream sis = new SequenceInputStream(en);
FileOutputStream fos = new FileOutputStream("E:\\hebing\\4.txt");

byte[] buf = new  byte[1024];
int len = 0;

//read(char[] cbuf)
//public int read(byte[] b)
//从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。
//在某些输入可用之前,此方法将阻塞。
while((len = sis.read(buf)) != -1)
{
fos.write(buf,0,len);
}
fos.close();
sis.close();

}
}

三十五.IO流切割文件

import java.io.*;
import java.util.*;

class IoTextDemo
{
public static void main(String[] args)throws IOException
{

//splitdocu();
sequenceInput();

}

public static void splitdocu() throws IOException
{
FileInputStream fis = new FileInputStream("E:\\hebing\\w.jpeg");
FileOutputStream fos = null;

byte[] buf = new byte[1024*15];
int len = 0;
int count = 0;
while((len = fis.read(buf)) != -1)
{
count++;
fos = new FileOutputStream("E:\\hebing\\"+count+".jpeg");
fos.write(buf,0,len);
}
fis.close();
fos.close();

}

public static void sequenceInput()throws IOException
{

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

for(int i = 1;i<4;i++)
{
list.add(new FileInputStream("E:\\hebing\\"+i+".jpeg")); //会报错,FileInputStream 无法转为String
}

final Iterator<FileInputStream> it = list.iterator();

//为什么要这么写,这个真不明白,因为只有Iterator有hasNext和next,Iterator跟Enumeration功能是一样的
//方法摘要
// boolean hasMoreElements()测试此枚举是否包含更多的元素
// E nextElement()如果此枚举对象至少还有一个可提供的元素,则返回此枚举的下一个元素。
Enumeration<FileInputStream> en = new Enumeration<FileInputStream>()
{
public boolean hasMoreElements()
{
return it.hasNext();
}

public FileInputStream nextElement()
{

return it.next();

}

};

SequenceInputStream sis = new SequenceInputStream(en);

FileOutputStream fos = new FileOutputStream("E:\\hebing\\f.jpeg");

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

三十六.IO包中其他类

打印流

PrintWriter与PrintStream

可以直接操作输入流和文件

序列流

SequenceInputStream

对多个流进行合并

操作对象 ,也就把堆内存中的对象存到文件中去,这个是他的重点!!!!!(硬盘),ObjectInputStream 与ObjectOutStream,被操作的对象需要实现Serializable(标记接口)

ObjectOutputStream 和 ObjectInputStream 分别与 FileOutputStream 和 FileInputStream
一起使用时,可以为应用程序提供对对象图形的持久存储(即把对象存到文件中),
ObjectInputStream 用于恢复那些以前序列化的对象。其他用途包括使用套接字流在主机之间传递对象,或者用于编组和解组远程通信系统中的实参和形参。

import java.io.*;

class IoTextDemo
{
public static void main(String[] args) throws Exception
{

///writeObj();
readObj();
}
public static void readObj() throws Exception
{
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("E:\\hebing\\obj.txt"));
Person p = (Person)ois.readObject();
System.out.println(p);

ois.close();

}

public static void writeObj() throws IOException
{
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("E:\\hebing\\obj.txt"));
//oos.writeObject(new Person("lisi",39));

//按理说new person(“lisi”,39)是应该在堆内存当中,这里就都存在对象当中,
//想把对象写在硬盘上(文件中)(用方法writeObject)
oos.writeObject(new Person("lisi",39,"kr"));//lisi:39:cn//只能把堆里面的序列化,
//不能把方法区里面的序列化

oos.close();
}
}

三十七.IO流RandomAccessFile

RandomAccessFile,该类不算是IO体系种子类,而是直接继承自Object。

但是它是IO包中成员。因为它具备读和写功能,内部封装一个数组,而且通过指针对数组的元素进行操作,可以通过getFilePointer获取指针位置。

同时可以通过seek改变指针的位置

其实完成读写的原理就是内部封装了字节输入流和输出流。

通过构造函数可以看出,该类只能操作文件。

而且操作文件还有模式,只读R,读写rw等。

如果模式为只读r,不会创建文件,会去读取一个已存在文件,如果该文件不存在,则会出现异常(R),而且该对象的构造函数要操作的文件不存在,会自动创建,如果存在则不会覆盖(W)

RandomAccessFile,随机访问文件,自身具备读写的方法。通过skipBytes(int x),seek(int x)来达到随机访问。!!!!!这个是他的优点.

import java.io.*;

class IoTextDemo
{
public static void main(String[] args) throws Exception
{
//writeFile();
//readFile();
writeFile_2();
}

public static void writeFile() throws IOException
{
RandomAccessFile raf = new RandomAccessFile("E:\\hebing\\ran1.txt","rw");

raf.write("王五".getBytes());//一个中文2个字节
//raf.write(97);//raf.write只写最低8位,如果超过就不能正确打印比如258,
//但是可以用WriteInt();
//文件中是王五a,读四个字节//因为记事本回去查GBK
raf.writeInt(97);//文件中是王五   a,中间有3个空格!!!(不是空格,应该是换行符,如果是空格,我自己写的三个空格,等会读年龄的时候读不出来)

raf.write("赵四".getBytes());
raf.writeInt(22);

raf.close();

}

public static void readFile() throws IOException
{
RandomAccessFile raf = new RandomAccessFile("E:\\hebing\\ran1.txt","r");

//之前打印
//name=王五
//age=97
//调整对象中指针   前后都可以
//raf.skipBytes(8); //跟下面效果一样,只是只能往前走不能往后走!!!!!
raf.seek(8);//相当于从第八个字节开始读  一个中文2个字节,int四个字节
//现在打印
//name=赵四
//age=22

byte[] buf =new byte[4];
raf.read(buf);
String name = new String(buf);
int age = raf.readInt();

System.out.println("name="+name);
System.out.println("age="+age);

raf.close();

}
//可以中间不写,直接写第四个,,或者修改之前写过的,在平常下载的时候,
//每一段数据都是单独一个线程进行写,这样就要求数据有规律,比如录入户口,16个字节写名字,四个字节写年龄
//20个字节是一个人,所以这样就可以分段读写
//如果是一般流,只能从头写到尾,只是多个线程从头写到位,那么数据不是按顺序来的,
//解码会报错(如下图)
public static void writeFile_2()throws IOException
{
RandomAccessFile raf = new RandomAccessFile("E:\\hebing\\ran1.txt","rw");
raf.seek(8*5);//从第四十个字节开始写

raf.write("周期".getBytes());
raf.writeInt(103);
raf.close();

}
}


三十八.IO流中的管道流

管道流

PopedinputStream 和PipedOutStream

输入输出可以直接进行连接,通过结合教程使用。

管道输入流应该连接到管道输出流;

管道输入流提供要写入管道输出流的所有数据字节。通常,

数据由某个线程从 PipedInputStream 对象读取,

并由其他线程将其写入到相应的 PipedOutputStream。

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

import java.io.*;

class IoTextDemo
{
public static void main(String[] args) throws IOException
{
PipedInputStream in = new PipedInputStream();
PipedOutputStream out = new PipedOutputStream ();
in.connect(out);
Read r = new Read(in);
Write w = new Write(out);
new Thread(r).start();
new Thread(w).start();
}
}

class Read implements Runnable
{
private PipedInputStream in;

Read(PipedInputStream in)
{

this.in = in;
}
public void run()
{

try
{
System.out.println("读取钱。。。没有数据就阻塞");
byte[] buf = new byte[1024];
int len = in.read(buf);// //阻塞式方法读取数据(如果没有数据就停在这,这时候其他线程就获取执行权)
System.out.println("读到数据,阻塞结束");

String s = new String(buf,0,len);
System.out.println(s);
in.close();
}
catch (IOException e)
{
throw new RuntimeException("管道读取失败");
}

//		  这种方法虽然OK,但是不适合代码原理展示
//		PrintStream ps = new PrintStream(System.out);
//		int line = 0;
//		try
//		{		//0-255的ASKII值
//				while((line = in.read()) !=  -1)
//				{
//
//					ps.println((char)line);
//				}
//				in.close();
//				ps.close();
//		}
//		catch (IOException e)
//		{
//			throw new RuntimeException("管道读取流失败");
//		}

}

}

class Write implements Runnable
{
private PipedOutputStream out;

Write(PipedOutputStream out)
{

this.out = out;
}

public void run()
{
try
{
System.out.println("开始写入数据,等待6秒");
Thread.sleep(6000);
out.write("da wang jiao wo lai xun shang".getBytes());
out.close();
}
catch (Exception e)
{
throw new RuntimeException("管道输出流失败");
}

}
}


三十九.IO流操作基本数据类型的流对象DataStream

重点在于:可以用于操作基本数据类型的数据的流对象,把基本数据和流结合起来!!!!

import java.io.*;

class IoTextDemo
{
public static void main(String[] args)throws IOException
{
//writeData();
readData();

}
public static void writeData()throws IOException
{

DataOutputStream dos = new DataOutputStream(new FileOutputStream("E:\\hebing\\data.txt"));
dos.writeInt(234);
dos.writeBoolean(true);
dos.writeDouble(9887.543);

dos.close();

}

public static void readData()throws IOException
{
//必须按照写的顺序读
DataInputStream dis = new DataInputStream(new FileInputStream("E:\\hebing\\data.txt"));
int num = dis.readInt();
boolean b =dis.readBoolean();
double d = dis.readDouble();

System.out.println("num="+num);
System.out.println("b="+b);
System.out.println("d="+d);
dis.close();

}
//以与机器无关方式使用 UTF-8 修改版编码将一个字符串写入基础输出流。
public static void writeUTFDemo()throws IOException
{
DataOutputStream dos = new DataOutputStream(new FileOutputStream("E:\\hebing\\data.txt"));
dos.writeUTF("你好");//用什么编码写就必须要用什么编码读
dos.close();
}

public static void readUTFDemo()throws IOException
{
DataInputStream dis = new DataInputStream(new FileInputStream("E:\\hebing\\data.txt"));

String s = dis.readUTF();
System.out.println(s);
dis.close();
}
}

四十.用于操作字节数组的流对象

ByteArrayInputStream:在构造的时候,需要接受数据源,而且数据源是一个字节数组。

ByteArrayOutputStream :在构造的时候,不用定义数据目的,因为该对象中已经内部封装了可变长度的字节数据,这就是数据的目的地(这就是他的重点)

下面这几个原理都是一样的

*************************************************

操作字节数组

ByteArrayInputStream与ByteArrayOutputStream

操作字符数据

CharArrayReader与CharArrayWrite

操作字符串

StringReader与StringWriter

**************************************************

因为这两个流对象都操作的数组,并没有使用系统资源(底层资源)

所以,不用进行close关闭。而且关不关闭,这个流对象都能继续使用
[b]1.源设备,[/b]
键盘 System.in , 硬盘 FileStream , 内存ArrayStream  !!!!!!!!!!

[b]2.目的设备:[/b]
控制台 System.out   硬盘FileStream, 内存ArrayStream. !!!!!!!!!!

这里的源和目的都是内存

用流的读写思想来操作数据

import java.io.*;
class IoTextDemo
{
public static void main (String[]  args)
{
//数据源
ByteArrayInputStream  bis = new ByteArrayInputSream(“ABCDEFG”.getBytes());//都在内存中

//数据目的
ByteArrayOutputStream bos = new ByteArrayOutputStream();//都在内存中//不用写目的,因为目的被封装在内部,可变的字符数组

int by = 0;
while((by = bis.read()) != -1)
{
bos.write(by);
}

System.out.println(bos.size());	//7
System.out.println(bos.toString()); //ABCDEFG

}

}

四十一.IO流转换流的字符编码

字符编码

字符流的出现是为了方便操作字符

更重要的是加入了编码转换

原理:!!!!!!

通过子类转换流来完成

InputStreamReader

OutputStreamWriter

在两个对象进行构造的时候加入字符集(也就是编码表)

常见的编码表

ASCII:美国标准信息交换码

用一个字节的7位可以表示

ISO8859-1:拉丁码表。欧洲码表

用一个字节的8位表示(比如打头为1,怎么写都跟前面的都不一样)

GBK2312:中国的中文编码表。(两个字节高位都是1,兼容ASCII码)

GBK:中国的中文编码表升级,融合了更多的中文文字符号

Unicode:国际标准码,融合了多种文字

所有文字都用两个字节来表示,java语言使用的就是unicode

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

import java.io.*;
class IoTextDemo
{
public static void main(String[] args) throw IOException
{
readText();
}

}

public static void readText() throws IOException
{
InputStreamReader isr = InputStreamReader(new FileInputStream(“gbk.txt”),”GBK”);

char[] buf = new char[10];
int len = isr.read(buf);

String str = new String (buf, 0, len);

System.out.printlb(str);
isr.close();

}

public static void writeText() throws IOException
{
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(“utf.txt”),”UTF-8”);

osw,write(“你好”);

osw.close();

}

四十二.编码解码

编码:字符串变成字节数组
解码:字节数组变成字符串

String -- >byte[] ;str.getBytes(charsetName);

byte  -- > String: new String(byte[],charsetName);

import  java.util.*;
class EncideDemo
{
public static void main(String[] args) throws Exception
{
String s = “你好”;
byte[]  b1 = s.getBytes(“utf-8”); //编码

System.out.println(Arrays.toString(b1));  //打印出他的字节
String s1 = new String(b1 , “UTF-8”);

System.out.println(“s1=”+s1);  //解码

}

//解码错了,在编回去,就OK了
public static void  method_1()
{
String s = "你好";
byte[] b1 = s.getBytes("GBK");

System.out.println(Arrays.toString(b1));  //打印出按照GBK编码的每个字节

String s1 = new String (b1,"iso8859-1");
System.out.println("s1="+s1);//打印解码出的字符

byte[] b2 = s1.getBytes("iso8859-1");
System.out.println(Arrays.toString(b2)); //按照iso8859编码出的每个字节

String s2 = new String(b2,"gbk");
System.out.println("s2= "+s2);
}
!!!!!
//解码错了,在编回去,不行了
//往回编的时候编错了,因为GBK,UTF-8都识别中文,服务器用的是IOS8859
//GBK用两个字节编码中文,UTF-8用三个,这是根本原因,用三个的原因,是因为识别到了使用三个字节的格式
//UTF编码原理
//utf编码是不定长编码,每一个字符的长度从1-6个字
//节不等。另外,utf编码自带简单的校验功能。一般来讲,英文字母都是用一个字节表示,而汉字使用三个字节
public static void  method_2()
{
String s = "你好";
byte[] b1 = s.getBytes("GBK");

System.out.println(Arrays.toString(b1));  //打印出按照GBK编码的每个字节

String s1 = new String (b1,"UTF-8");
System.out.println("s1="+s1);//打印解码出的字符

byte[] b2 = s1.getBytes("UTF-8");
System.out.println(Arrays.toString(b2)); //按照iso8859编码出的每个字节

String s2 = new String(b2,"gbk");
System.out.println("s2= "+s2);
}

}

四十三.联通问题

UTF-8是读取三个字节成一个中文,

怎么判断取一个字节,还是去两个字节,还是三个字节

联通这两个字的编码正好符合UTF-8取两个字节的规则,所以乱码,他是三个字节做一个中文

开头 0  读一个字节

字节 1 0
位 6-0

开头110

第二字节10   读两个字节

字节 1 1
1 0 位 10-6

字节 2 1
0 位 5-0

第三个字节

字节 1 1
1 1 0位 15-12

字节 2 1
0 位 11-6

字节 3 1
0 位 5-0

class EncodeDemo2
{
public static void main(String[] args)throws Exception
{
String s = "联通";
byte[] by = s.getBytes("gbk");
for(byte b:by)
{
System.out.println(Integer.toBinaryString(b&255))//打印成二进制//取最后八位
}

}

}


四十四.练习

需求:
有五个学生,每个学生有三门课的成绩

从键盘输入以上数据(包括姓名,三门课成绩),

输入的格式:如:zhangsan , 30 , 40 ,60计算出总成绩,

并把学生的信息和计算出的总分数高低顺序存档在磁盘文件”stud.txt”中

1.描述学生对象

2.定义一个可操作学生对象的工具类。

思想:

1.通过获取键盘录入一行数据,并将该行中的信息取出封装成对象。

2.因为学生有很多,那么就需要存储,使用到集合,因为对学生的总分排序

所以可以使用TreeSet.

3.将集合的信息写入到一个文件中。

import java.io.*;
import java.util.*;

class IoTextDemo
{
public static void main(String[] args) throws IOException
{
TreeSet<Student> stus = StudentInfoTool.getStudents();//默认顺序从小到大,现在从大到小
StudentInfoTool.writeToFile(stus);

}
}
class StudentInfoTool
{
public static TreeSet<Student> getStudents()throws IOException
{
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
TreeSet<Student> ts = new TreeSet<Student>();

String line = null;

while((line = bufr.readLine()) != null)
{
if("over".equals(line))
{
break;
}
//把输入的字符按逗号区分开
String[] info = line.split(",");
//自己写的时候就卡在这个地方(怎么把输入的数据添加到集合中)
//parseInt(String s)将字符串参数作为有符号的十进制数进行解析
Student stu = new Student(info[0],Integer.parseInt(info[1]),Integer.parseInt(info[2]),Integer.parseInt(info[3]));

ts.add(stu);
}
bufr.close();

return ts;
}
public static void writeToFile(TreeSet<Student> ts1) throws IOException
{
BufferedWriter bufw = new BufferedWriter(new  FileWriter("E:\\hebing\\Stu_info.txt") );

for(Student s:ts1)
{
bufw.write(s.toString()+'\t');
bufw.write(s.getSum()+"");
bufw.newLine();
bufw.flush();

}

bufw.close();

}
}

//因为要排序,所以选择TreeSet,这里就用排序两种方法之一实现Comparable
class Student implements Comparable<Student>
{
private String name;
private int cn;
private int en;
private int math;
private int sum;

Student(String name , int cn , int en , int math)
{
this.name = name;
this.cn = cn;
this.en = en;
this.math = math;
this.sum = cn+en+math;

}
public String getName()
{
return name;
}
public int getSum()
{
return sum;
}
public int hashCode()
{

return name.hashCode()+sum*2;

}
public boolean equals(Student obj)
{

return (this.name.equals(obj.name))&&(this.sum == obj.sum);

}
//继承comparable需要复写compareTo这个方法
public  int compareTo(Student s)
{
//这个地方写错了!!!!!
int num = new Integer(this.sum).compareTo(new Integer(s.sum));

if(num == 0)
{

return this.name.compareTo(s.name);
}
return num;

}
public String toString()
{
//等会把数据按照这样的格式写入文件中
return name+","+en+","+cn+","+math+","+sum;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: