java流为什么不能读写图片?java 中简述使用流进行读写文本文件的步骤
大家好,java流为什么不能读写图片相信很多的网友都不是很明白,包括java 中简述使用流进行读写文本文件的步骤也是一样,不过没有关系,接下来就来为大家分享关于java流为什么不能读写图片和java 中简述使用流进行读写文本文件的步骤的一些知识点,大家可以关注收藏,免得下次来找不到哦,下面我们开始吧!
为什么Java中的file类无法只能操作不能读写
说下我的理解,通常意思下,我们理解的文件,其实包含两部分,一部分是指保存在磁盘上的文件的具体内容,另一部分指的是保存在操作系统文件系统里面的文件名称,目录那些东西。(这里你可以去搜索下 linux inode理解相关的概念,这里我也不是很熟)。
文件系统是操作系统封装磁盘操作产生的一层东西,我们只能通过操作系统提供的文件系统的API去操作磁盘。(这里可以去学习下操作系统相关的知识)。
java中的FIle指的是文件系统里面的一个file,这个对象,只包含文件的一些元数据,文件大小,位置,创建时间,修改时间,创建人,权限等等一系列的文件元数据,它是不包含文件具体的内容的。所以你只能操作它,不能读写。所谓的操作,也就是对文件系统那一棵文件目录树进行增删改查的操作。
file这个对象里,应该包含这个文件在磁盘上的具体位置,通过这个位置,你就可以通过文件系统的API进行文件的读写了。(这里,我的理解是这样,具体是不是这样,我也不确定,可以去搜索 posix标准查看通用的一些文件操作的API来验证下)。
而对文件具体内容的操作,你必须通过IO操作去实现。这里过程大概如下,涉及操作系统跟驱动相关的过程,去百度吧,我也不是很熟。
java操作流的方法
这是一对继承于InputStream和OutputStream的类,用于本地文件读写(二进制格式读写并且是顺序读写,读和写要分别创建出不同的文件流对象);
本地文件读写编程的基本过程为:
①生成文件流对象(对文件读操作时应该为FileInputStream类,而文件写应该为FileOutputStream类);
②调用FileInputStream或FileOutputStream类中的功能函数如read()、write(int b)等)读写文件内容;
③关闭文件(close())。
实例:流文件读写
流文件的单元是字节,所以它不但可以读写文本文件,也可以读写图片、声音、影像文件,这种特点非常有用,因为我们可以把这种文件变成流,然后在网络上传输。
问题是有了通用的流文件以后,为什么还要专门的字符流呢?这是因为文本可以用不同的方式存储,可以是普通的文本(UTF-8编码方式),ASCII文本和Unicode文本,字符流对象可以进行必要的转换,从而读出正确的文本。
有人认为流文件不能读写文本文件,这其实是个误会,因为文本文件本质上也是由字节组成的,当然是流文件的一种。作为读写文件的全体,这是没问题的,但是,如果要处理每次读入的内容,就最好使用字符流。
所以在文本文件处理时,使用字符流是个最常用的方法。
样例:
import java.io.*;
public class FileStreamDemo{
public static void main(String[] args) throws IOException{
//创建两个文件,face.gif是已经存在文件,newFace.gif是新创建的文件
File inFile= new File("face.gif");
File outFile= new File("newFace.gif");
//创建流文件读入与写出类
FileInputStream inStream= new FileInputStream(inFile);
FileOutputStream outStream= new FileOutputStream(outFile);
//通过available方法取得流的最大字符数
byte[] inOutb= new byte[inStream.available()];
inStream.read(inOutb);//读入流,保存在byte数组
outStream.write(inOutb);//写出流,保存在文件newFace.gif中
inStream.close();
outStream.close();
}
}
实例:读写任意大文件应用
因为byte数组最大存储值不超过64M,所以当一个文件大于60M的时候,需要分开几个流操作。我们把上面的程序作一个修改,就可以写入任意大小的文件。这个程序应用了FileInputStream类的方法如下:
read(byte[] b,int off,int len)
把特定位置的流内容读入数组,已经读入byte[]数组的内容,会在流文件中删除。
程序运行的结果会产生一个新文件。
样例:
import java.io.*;
public class FileStreamDemo2{
public static void main(String[] args) throws IOException{
//创建两个文件
File inFile= new File("tcty36.rm");
File outFile= new File("newtcty36.rm");
//最大的流为60Mb,当文件的容量大于60Mb的时候便分开流
final int MAX_BYTE= 60000000;
long streamTotal= 0;//接受流的容量
int streamNum= 0;//流需要分开的数量
int leave= 0;//文件剩下的字符数
byte[] inOutb;//byte数组接受文件的数据
//创建流文件读入与写出类
FileInputStream inStream= new FileInputStream(inFile);
FileOutputStream outStream= new FileOutputStream(outFile);
//通过available方法取得流的最大字符数
streamTotal= inStream.available();
//取得流文件需要分开的数量
streamNum=(int)Math.floor(streamTotal/MAX_BYTE);
//分开文件之后,剩余的数量
leave=(int)streamTotal% MAX_BYTE;
//文件的容量大于60Mb时进入循环
if(streamNum> 0){
for(int i= 0; i< streamNum;++i){
inOutb= new byte[MAX_BYTE];
//读入流,保存在byte数组
inStream.read(inOutb, 0, MAX_BYTE);
outStream.write(inOutb);//写出流
outStream.flush();//更新写出的结果
}
}
//写出剩下的流数据
inOutb= new byte[leave];
inStream.read(inOutb, 0, leave);
outStream.write(inOutb);
outStream.flush();
inStream.close();
outStream.close();
}
}
六、管道PipedInputStream/PipedOutputStream类:
当需要在两个线程中读写数据的时候,由于线程的并发执行,读写的同步问题可能会发生困难,这时候可以使用管道,管道事实上是一个队列。
管道是由系统维护的一个缓冲区,当然程序员也可以自己直接指定该缓冲区的大小(只需要设置管道流类中的PIPE_SIZE属性的值)。当生产者生产出数据后,只需要将数据写入管道中,消费者只需要从管道中读取所需要的数据。利用管道的这种机制,可以将一个线程的输出结果直接连接到另一个线程的输入端口,实现两者之间的数据直接传送。
线程1
线程2
临时文件
管道
1.管道的连接:
方法之一是通过构造函数直接将某一个程序的输出作为另一个程序的输入,在定义对象时指明目标管道对象
PipedInputStream pInput=new PipedInputStream();
PipedOutputStream pOutput= new PipedOutputStream(pInput);
方法之二是利用双方类中的任一个成员函数 connect()相连接
PipedInputStream pInput=new PipedInputStream();
PipedOutputStream pOutput= new PipedOutputStream();
pinput.connect(pOutput);
2.管道的输入与输出:
输出管道对象调用write()成员函数输出数据(即向管道的输入端发送数据);而输入管道对象调用read()成员函数可以读起数据(即从输出管道中获得数据)。这主要是借助系统所提供的缓冲机制来实现的。
实例:Java的管道的输入与输出
import java.io.*;
public class PipedIO//程序运行后将sendFile文件的内容拷贝到receiverFile文件中
{
public static void main(String args[])
{
try
{
//构造读写的管道流对象
PipedInputStream pis=new PipedInputStream();
PipedOutputStream pos=new PipedOutputStream();
//实现关联
pos.connect(pis);
//构造两个线程,并且启动。
new Sender(pos,"c:\\text2.txt").start();
new Receiver(pis,"c:\\text3.txt").start();
}
catch(IOException e)
{
System.out.println("Pipe Error"+ e);
}
}
}
//线程发送
class Sender extends Thread
{
PipedOutputStream pos;
File file;
//构造方法
Sender(PipedOutputStream pos, String fileName)
{
this.pos=pos;
file=new File(fileName);
}
//线程运行方法
public void run()
{
try
{
//读文件内容
FileInputStream fs=new FileInputStream(file);
int data;
while((data=fs.read())!=-1)
{
//写入管道始端
pos.write(data);
}
pos.close();
}
catch(IOException e)
{
System.out.println("Sender Error"+e);
}
}
}
//线程读
class Receiver extends Thread
{
PipedInputStream pis;
File file;
//构造方法
Receiver(PipedInputStream pis, String fileName)
{
this.pis=pis;
file=new File(fileName);
}
//线程运行
public void run()
{
try
{
//写文件流对象
FileOutputStream fs=new FileOutputStream(file);
int data;
//从管道末端读
while((data=pis.read())!=-1)
{
//写入本地文件
fs.write(data);
}
pis.close();
}
catch(IOException e)
{
System.out.println("Receiver Error"+e);
}
}
}
七、随机文件读写:RandomAccessFile类
它直接继承于Object类而非InputStream/OutputStream类,从而可以实现读写文件中任何位置中的数据(只需要改变文件的读写位置的指针)。
编程步骤:
①生成流对象并且指明读写类型;
②移动读写位置;
③读写文件内容;
④关闭文件。
另外由于RandomAccessFile类实现了DataOutput与DataInput接口,因而利用它可以读写Java中的不同类型的基本类型数据(比如采用readLong()方法读取长整数,而利用readInt()方法可以读出整数值等)。
程序实例:
利用随机数据流RandomAccessFile类来实现记录用户在键盘的输入,每执行一次,将用户的键盘输入存储在指定的UserInput.txt文件中。
import java.io.*;
public class RandomFileRW
{
public static void main(String args[])
{
StringBuffer buf=new StringBuffer();
char ch;
try
{
while((ch=(char)System.in.read())!='\n')
{
buf.append(ch);
}
//读写方式可以为"r" or"rw"
RandomAccessFile myFileStream=new RandomAccessFile("c:\\UserInput.txt","rw");
myFileStream.seek(myFileStream.length());
myFileStream.writeBytes(buf.toString());
//将用户从键盘输入的内容添加到文件的尾部
myFileStream.close();
}
catch(IOException e)
{
}
}
}
八、DataInput/DataOutput接口:
实现与机器无关的各种数据格式读写(如readChar()、readInt()、readLong()、readFloat(),而readLine()将返回一个String)。其中RandomAccessFile类实现了该接口,具有比FileInputStream或FileOutputStream类更灵活的数据读写方式。
java 中简述使用流进行读写文本文件的步骤
一、Java IO学习基础之读写文本文件
Java的IO操作都是基于流进行操作的,为了提高读写效率一般需要进行缓冲。
简单的示例程序如下:
/**
*读出1.txt中的内容,写入2.txt中
*
*/
import java.io.*;
public class ReadWriteFile{
public static void main(String[] args){
try{
File read= new File("c:\\1.txt");
File write= new File("c:\\2.txt");
BufferedReader br= new BufferedReader(
new FileReader(read));
BufferedWriter bw= new BufferedWriter(
new FileWriter(write));
String temp= null;
temp= br.readLine();
while(temp!= null){
//写文件
bw.write(temp+"\r\n");//只适用Windows系统
//继续读文件
temp= br.readLine();
}
bw.close();
br.close();
}catch(FileNotFoundException e){//文件未找到
System.out.println(e);
}catch(IOException e){
System.out.println(e);
}
}
}
以上是一个比较简单的基础示例。本文上下两部分都是从网上摘抄,合并在一起,方便下自己以后查找。
二、Java IO学习笔记+代码
文件对象的生成和文件的创建
/*
* ProcessFileName.java
*
* Created on 2006年8月22日,下午3:10
*
*文件对象的生成和文件的创建
*/
package study.iostudy;
import java.io.*;
public class GenerateFile
{
public static void main(String[] args)
{
File dirObject= new File("d:\\mydir");
File fileObject1= new File("oneFirst.txt");
File fileObject2= new File("d:\\mydir","firstFile.txt");
System.out.println(fileObject2);
try
{
dirObject.mkdir();
}catch(SecurityException e)
{
e.printStackTrace();
}
try
{
fileObject2.createNewFile();
fileObject1.createNewFile();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
文件名的处理
/*
* ProcessFileName.java
*
* Created on 2006年8月22日,下午3:29
*
*文件名的处理
*/
package study.iostudy;
import java.io.*;
/*
*文件名的处理
* String getName();获得文件的名称,不包含文件所在的路径。
* String getPath();获得文件的路径。
* String getAbsolutePath();获得文件的绝对路径。
* String getParent();获得文件的上一级目录的名称。
* String renameTo(File newName);按参数中给定的完整路径更改当前的文件名。
* int compareTo(File pathName);按照字典顺序比较两个文件对象的路径。
* boolean isAbsolute();测试文件对象的路径是不是绝对路径。
*/
public class ProcesserFileName
{
public static void main(String[] args)
{
File fileObject1= new File("d:\\mydir\\firstFile.txt");
File fileObject2= new File("d:\\firstFile.txt");
boolean pathAbsolute= fileObject1.isAbsolute();
System.out.println("************************");
System.out.println("There are some information of fileObject1's file name:");
System.out.println("fileObject1:"+ fileObject1);
System.out.println("fileObject2:"+ fileObject2);
System.out.println("file name:"+ fileObject1.getName());
System.out.println("file path:"+ fileObject1.getPath());
System.out.println("file absolute path:"+ fileObject1.getAbsolutePath());
System.out.println("file's parent directory:"+ fileObject1.getParent());
System.out.println("file's absoulte path:"+ pathAbsolute);
int sameName= fileObject1.compareTo(fileObject2);
System.out.println("fileObject1 compare to fileObject2:"+ sameName);
fileObject1.renameTo(fileObject2);
System.out.println("file's new name:"+ fileObject1.getName());
}
}
测试和设置文件属性
/*
* SetterFileAttribute.java
*
* Created on 2006年8月22日,下午3:51
*
*测试和设置文件属性
*/
package study.iostudy;
import java.io.*;
public class SetterFileAttribute
{
/*
* File类中提供的有关文件属性测试方面的方法有以下几种:
* boolean exists();测试当前文件对象指示的文件是否存在。
* boolean isFile();测试当前文件对象是不是文件。
* boolean isDirectory();测试当前文件对象是不是目录。
* boolean canRead();测试当前文件对象是否可读。
* boolean canWrite();测试当前文件对象是否可写。
* boolean setReadOnly();将当前文件对象设置为只读。
* long length();获得当前文件对象的长度。
*/
public static void main(String[] args)
{
File dirObject= new File("d:\\mydir");
File fileObject= new File("d:\\mydir\\firstFile.txt");
try
{
dirObject.mkdir();
fileObject.createNewFile();
}catch(IOException e)
{
e.printStackTrace();
}
System.out.println("************************");
System.out.println("there are some information about property of file object:");
System.out.println("file object:"+ fileObject);
System.out.println("file exist?"+ fileObject.exists());
System.out.println("Is a file?"+ fileObject.isFile());
System.out.println("Is a directory?"+ fileObject.isDirectory());
System.out.println("Can read this file?"+ fileObject.canRead());
System.out.println("Can write this fie?"+ fileObject.canWrite());
long fileLen= fileObject.length();
System.out.println("file length:"+fileLen);
boolean fileRead= fileObject.setReadOnly();
System.out.println(fileRead);
System.out.println("Can read this file?"+ fileObject.canRead());
System.out.println("Can write this fie?"+ fileObject.canWrite());
System.out.println("************************");
}
}
文件操作方法
/*
* FileOperation.java
*
* Created on 2006年8月22日,下午4:25
*
*文件操作方法
*/
package study.iostudy;
import java.io.*;
/*
*有关文件操作方面的方法有如下几种:
* boolean createNewFile();根据当前的文件对象创建一个新的文件。
* boolean mkdir();根据当前的文件对象生成一目录,也就是指定路径下的文件夹。
* boolean mkdirs();也是根据当前的文件对象生成一个目录,
*不同的地方在于该方法即使创建目录失败,
*也会成功参数中指定的所有父目录。
* boolean delete();删除当前的文件。
* void deleteOnExit();当前Java虚拟机终止时删除当前的文件。
* String list();列出当前目录下的文件。
*/
public class FileOperation
*找出一个目录下所有的文件
package study.iostudy;
import java.io.*;
public class SearchFile
{
public static void main(String[] args)
{
File dirObject= new File("D:\\aa");
Filter1 filterObj1= new Filter1("HTML");
Filter2 filterObj2= new Filter2("Applet");
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
System.out.println("list HTML files in directory:"+ dirObject);
String[] filesObj1= dirObject.list(filterObj1);
for(int i= 0; i< filesObj1.length; i++)
{
File fileObject= new File(dirObject, filesObj1[i]);
System.out.println(((fileObject.isFile())
?"HTML file:":"sub directory:")+ fileObject);
}
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
String[] filesObj2= dirObject.list(filterObj2);
for(int i= 0; i< filesObj2.length; i++)
{
File fileObject= new File(dirObject, filesObj2[i]);
System.out.println(((fileObject.isFile())
?"htm file:":"sub directory:")+ fileObject);
}
}
}
class Filter1 implements FilenameFilter
{
String fileExtent;
Filter1(String extentObj)
{
fileExtent= extentObj;
}
public boolean accept(File dir, String name)
{
return name.endsWith("."+ fileExtent);
}
}
class Filter2 implements FilenameFilter
{
String fileName;
Filter2(String fileName)
{
this.fileName= fileName;
字符流处理
* ProcesserCharacterStream.java
*字符流处理
*
* java.io包中加入了专门用于字符流处理的类,这些类都是Reader和Writer类的子类,
* Reader和Writer是两个抽象类,只提供了一系列用于字符流处理的接口,不能生成这
*两个类的实例。
* java.io包中用于字符流处理的最基本的类是InputStreamReader和OutputStreamWriter,
*用来在字节流和字符流之间作为中介。
*
*下面是InputStreamReader类和OutputStreamWriter类的常用方法:
*
* public InputStreamReader(InputStream in)
*根据当前平台缺省的编码规范,基于字节流in生成一个输入字符流。
* public InputStreamReader(InputStream in, String sysCode)throws UnSupportedEncodingException
*按照参数sysCode指定的编码规范,基于字节流in构造输入字符流,如果不支持参数sysCode中指定的编码规范,就会产生异常。
* public OutputStreamWriter(OutputStream out)
*根据当前平台缺省的编码规范,基于字节流out生成一个输入字符流。
* public OutputStreamWriter(OutputStream out, String sysCode) throws UnsupportedEncodingException
*按照参数sysCode指定的编码规范,基于字节流out构造输入字符流,如果不支持参数sysCode中指定的编码规范,就会产生异常。
* public String getEncoding()
*获得当前字符流使用的编码方式。
* public void close() throws IOException
*用于关闭流。
* public int read() throws IOException
*用于读取一个字符。
* public int read(char[] cbuf, int off, int len)
*用于读取len个字符到数组cbuf的索引off处。
* public void write(char[] cbuf, int off, int len) throws IOException
*将字符数组cbuf中从索引off处开始的len个字符写入输出流。
* public void write(int c) throws IOException
*将单个字符写入输入流。
* public void write(String str, int off, int len) throws IOException
*将字符串str中从索引off位置开始的ltn个字符写入输出流。
*
*此外,为了提高字符流处理的效率,在Java语言中,引入了BufferedReader和BufferWriter类,这两个类对字符流进行块处理。
*两个类的常用方法如下:
* public BufferedReader(Reader in)
*用于基于普通字符输入流in生成相应的缓冲流。
* public BufferedReader(Reader in, int bufSize)
*用于基于普通字符输入流in生成相应的缓冲流,缓冲区大小为参数bufSize指定。
* public BufferedWriter(Writer out)
*用于基于普通字符输入流out生成相应的缓冲流。
* public BufferedWriter(Writer out, int bufSize)
*用于基于普通字符输入流out生在相应缓冲流,缓冲流大小为参数bufSize指定。
* public String readLine() throws IOException
*用于从输入流中读取一行字符。
* public void newLine() throws IOException
*用于向字符输入流中写入一行结束标记,值得注意的是,该标记不是简单的换行符"\n",而是系统定义的属性line.separator。
在上面的程序中,我们首先声明了FileInputStream类对象inStream和
* FileOutputStream类的对象outStream,接着声明了BufferInputStream
*类对象bufObj、BufferedOutputStream类对象bufOutObj、
* DataInputStream类对象dataInObj以及PushbackInputStream类对象pushObj,
*在try代码块中对上面这些对象进行初始化,程序的目的是通过BufferedInputStream
*类对象bufInObj和BufferedOutputStream类对象bufOutObj将secondFile.txt
*文件中内容输出到屏幕,并将该文件的内容写入thirdFile.txt文件中,值得注意的是,
*将secondFile.txt文件中的内容输出之前,程序中使用
*"System.out.println(dataInObj.readBoolean());"语句根据readBoolean()结果
*输出了true,而secondFile.txt文件开始内容为“Modify”,和一个字符为M,
*因此输出的文件内容没有“M”字符,thirdFile.txt文件中也比secondFile.txt
*文件少第一个字符“M”。随后,通过PushbackInputStream类对象pushObj读取
* thirdFile.txt文件中的内容,输出读到的字符,当读到的不是字符,输出回车,将字符
*数组pushByte写回到thirdFile.txt文件中,也就是“ok”写回文件中。
*对象串行化
*对象通过写出描述自己状态的数值来记录自己,这个过程叫做对象串行化。对象的寿命通
*常是随着生成该对象的程序的终止而终止,在有些情况下,需要将对象的状态保存下来,然后
*在必要的时候将对象恢复,值得注意的是,如果变量是另一个对象的引用,则引用的对象也要
*串行化,串行化是一个递归的过程,可能会涉及到一个复杂树结构的串行化,比如包括原有对
*象,对象的对象等。
*在java.io包中,接口Serializable是实现对象串行化的工具,只有实现了Serializable
*的对象才可以被串行化。Serializable接口中没有任何的方法,当一个类声明实现Seriali-
* zable接口时,只是表明该类遵循串行化协议,而不需要实现任何特殊的方法。
*在进行对象串行化时,需要注意将串行化的对象和输入、输出流联系起来,首先通过对
*象输出流将对象状态保存下来,然后通过对象输入流将对象状态恢复。
关于java流为什么不能读写图片,java 中简述使用流进行读写文本文件的步骤的介绍到此结束,希望对大家有所帮助。