Java 读取文本文件

Java 读取文本文件FilePathFileReader和FileWriterInputStreamReader和OutputStreamWriterFileInputStream和FileOutputStreamBufferedReaderFileFile代表目录或者文件File类的实例是不可变的;也就是说,一旦创建,由File对象表示的抽象路径名将永远不会改变。下面…

大家好,又见面了,我是你们的朋友全栈君。

我想用Java 读取文本文件(txt)中的字符,但是对Java的文件操作不怎么熟悉,于是开始翻官方文档,解决了如何从文件中读取一行或者全部数据的问题。

File

File 代表目录或者文件
File类的实例是不可变的;也就是说,一旦创建,由File对象表示的抽象路径名将永远不会改变。下面是File 类的部分方法:

public File(String pathname)
public File(String parent, String child)
public File(File parent, String child)
public File(URI uri)

public String getName() 
public String getParent()
public String getPath()
public URL toURL()
public boolean canRead()
public boolean canWrite()
public boolean exists()
public boolean isDirectory()
public boolean isFile()
public boolean isHidden()
public long lastModified()
public long length()
public boolean createNewFile()
public boolean delete()
public void deleteOnExit()
....

File 类本身并没有提供用于输入输出的方法,它只是代表了计算机中的文件或目录。

FileReader

FileReader 继承自InputStreamReader ,在类文件中只看到了新增的三个构造方法:
public FileReader(String fileName)
public FileReader(File file)
public FileReader(FileDescriptor fd)
文档说FileReader是用于读取字符文件,将文件以字符流的形式读出,但是仍然没有看到输入的方法,接下来看看它们的父类,看父类有没有我们要的方法。

InputStreamReader

InputStreamReader 继承自抽象类 Reader ,下面是InputstreamReader的全部公共方法:

  //所有的构造方法参数都是InputStream
  public InputStreamReader(InputStream in) 
  public InputStreamReader(InputStream in, String charsetName) //用指定字符集创建对象
  public InputStreamReader(InputStream in, Charset cs)
  public InputStreamReader(InputStream in, CharsetDecoder dec)
  
  public String getEncoding() //获取字符集
  public int read() //读取单个字符的字符集编码,如果流被读完,返回-1
  public int read(char cbuf[], int offset, int length) //读取部分字符到字符数组cbuf
  public boolean ready() //如果该流的输入缓冲区非空,返回true
  public void close()

终于看到read()方法了,现在我知道怎么从文本文件中读取字符了:

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

        String fileName ="C:\\Users\\lin\\Desktop\\English.txt";
        FileReader fileReader = new FileReader(fileName);

        char[] chars = new char[10];

        fileReader.read(chars,0,9);//先读取十个字符试试

        for(char ch:chars){
            System.out.print(ch);
        }
    }
}

文件中的内容
这里写图片描述
运行结果:

insult ��

中文乱码,先不管它。
但不管是FileReader 还是 InputStreamReader,都只有两个方法可以用于读出数据 :
public int read()public int read(char[] cbuf,int offset,int length)
显然这种简易的方法不能满足我的需求,然后我又找到了BufferedReader

BufferedReader(解决方法在这里)

下面是BufferedReader的文档(jdk1.8)以及来自英语渣不负责任的翻译:

Reads text from a character-input stream, buffering characters so as to provide for the efficient reading of characters, arrays, and lines.
从字符输入流读取文本,并且缓冲字符,以便提供对字符、数组和行的有效读取。
The buffer size may be specified, or the default size may be used. The default is large enough for most purposes.
可以指定缓冲字符的数量,如果没有指定的话会使用默认值,这个默认值对大多数的需求来说是足够大的。
In general, each read request made of a Reader causes a corresponding read request to be made of the underlying character or byte stream.
通常来说,每个由Reader构建的读取请求会引起相应的字符或是字节流读取请求。
It is therefore advisable to wrap a BufferedReader around any Reader whose read() operations may be costly, such as FileReaders and InputStreamReaders. For example,
因此建议用BufferedReader 包装 可能耗费高昂代价的Reader的read() 方法,比如:
BufferedReader in = new BufferedReader(new FileReader("foo.in"));
will buffer the input from the specified file.
将会缓存指定的输入流.
Without buffering, each invocation of read() or readLine() could cause bytes to be read from the file, converted into characters, and then returned, which can be very inefficient.
如果没有缓存,每次调用read() 或者readLine() 方法都会从文件中读取字节,将字节转换为字符,然后再返回,这样是很低效的。
Programs that use DataInputStreams for textual input can be localized by replacing each DataInputStream with an appropriate BufferedReader.

下面是BufferedReader 的全部公有方法:

public BufferedReader(Reader in, int sz)
public BufferedReader(Reader in)
public int read()
public int read(char cbuf[], int off, int len)
public String readLine()
public long skip(long n)
public boolean ready()
public boolean markSupported()
public void mark(int readAheadLimit)
public void reset()
public void close()
public Stream<String> lines()

文档说FileReaderread 方法是比较低效的,同时也给出了解决方案:用BufferedReader 包装FileReader, 于是我修改了我的代码:

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

        String fileName ="C:\\Users\\lin\\Desktop\\English.txt";
        FileReader fileReader = new FileReader(fileName);

        BufferedReader bufferedReader = new BufferedReader(fileReader);
        
        System.out.println(bufferedReader.readLine());

        bufferedReader.close();
        fileReader.close();
        
    }
}

运行结果:

insult ����

感觉好多了,如果要读取文本文件中的全部数据,我是这样做的:

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

        String fileName ="C:\\Users\\lin\\Desktop\\English.txt";
        FileReader fileReader = new FileReader(fileName);

        BufferedReader bufferedReader = new BufferedReader(fileReader);

        String line =bufferedReader.readLine();

        while (line!=null){
            System.out.println(line);
            line = bufferedReader.readLine();
        }

        bufferedReader.close();
        fileReader.close();

    }
}

运行结果:

insult ����
harsh �����ġ��̶���
intimidate ����
compromise��Э
executionִ��
novel �����С˵
engage����������
revenue-generating ����-���� ����
sweat ����
ownership ����Ȩ
synchronized ͬ��
asynchronized �첽
employee ְ��
hint ���� ���� ��ʾ
indication ָʾ
denote ָ������������ʾ
portion ����
offset ƫ����

解决中文乱码

翻文档的时候看到InputStreamReader 里有一个public String getEncoding() 的方法,jdk1.8对其的描述如下:

Returns the name of the character encoding being used by this stream.
返回该流的字符编码名
If the encoding has an historical name then that name is returned; otherwise the encoding’s canonical(权威的,牧师的) name is returned.
如果这个字符编码有历史名就返回历史名,否则返回规范名。简而言之就是返回该流的字符编码名。
If this instance was created with the InputStreamReader(InputStream, String) constructor then the returned name, being unique for the encoding, may differ from the name passed to the constructor. This method will return null if the stream has been closed.
如果这个实例是由InputStreamReader(InputStream, String) 这个构造方法创建的,那么返回的独一无二的编码名可能和传过来的的形参不同。如果该流被关闭,则返回null

需要注意的是这个方法返回的是文件流的字符编码,不是文件的编码。
然后我就用了这个方法,发现控制台输出的字符编码是UTF8

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

        String fileName ="C:\\Users\\lin\\Desktop\\English.txt";
        FileReader fileReader = new FileReader(fileName);

        BufferedReader bufferedReader = new BufferedReader(fileReader);
        
        System.out.println("字符集:"+fileReader.getEncoding()); 
        
        String line =bufferedReader.readLine();

        while (line!=null){
            System.out.println(line);
            line = bufferedReader.readLine();
        }

        bufferedReader.close();
        fileReader.close();

    }
}

我记得win10记事本的默认字符编码是ASCI,于是我把English.txt 改成UTF8 控制台就能够正常显示中文了。
这里写图片描述

FileInputStream

此前介绍的都是用于输出字符流的Java API。
FileInputStream 是字节输出流,将文件以字节流的形式读出
FileInputStream 继承自抽象类InputStream

A FileInputStream obtains input bytes from a file in a file system. What files are available depends on the host environment.
FileInputStream 从文件系统的文件中获取输入的二进制字节。文件是否可用取决于本地的计算机。
FileInputStream is meant for reading streams of raw bytes such as image data. For reading streams of characters, consider using FileReader.
FileInputStream 是为了读取诸如图像此类的原生的二进制字节而设计的。如果要读取字符流,考虑使用FileReader


读出对应着写入,每一个InputStream或者Reader都对应着一个OutputStream或者Writer,后者和前者大体相同,不再赘述。
另外,Java I/O 之所以设计得 看起来如此复杂 ,是因为使用了***装饰模式***,目的是在不破坏原有代码的情况下为功能的扩展提供比继承更好的灵活性,亦即 对修改关闭,对扩展开放

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/151711.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 细数家庭安防五大乱象 何时能步入正轨

    细数家庭安防五大乱象 何时能步入正轨虽然智能家居行业在我国的成长已逾十个年头了,但是目前市场离成型仍然有一段距离。市场上可谓“乱象”丛生,这些绊脚石严重阻碍了行业的良性发展。市场乱象繁生,智能家居从概念炒作到价格高抬,相关预测显示,若真如电商一样打起价格战,智能家居就要认输了。“智能家居”(SmartHome)最早被提出和应用是在上世纪80年代的欧美和日本,2000年才被引入中国。世纪…

  • 马哥学习—-李洋个人笔记–启动故障排除

    马哥学习—-李洋个人笔记–启动故障排除故障1删除/boot之后的恢复步骤:1重启电源,迅速按esc进去选择启动模式,然后选cd-rom这项(从光驱启动)2重启后进入救援模式(选择rescue),选择语言和键盘布局后,一路回车到下一步。3询问是否需要网络选项,一般来说,救援模式不需要网络,选择no,回车进入下一步。4这一步提示内容大意为:救援系统将尝试寻找你的linux安装,并在目录mnt/sysimage下安装它…

  • 接口测试-Mock测试方法

    接口测试-Mock测试方法一、关于Mock测试1、什么是Mock测试?Mock测试就是在测试过程中,对于某些不容易构造(如HttpServletRequest必须在Servlet容器中才能构造出来)或者不容易获取的比较复杂的对象(如JDBC中的ResultSet对象),用一个虚拟的对象(Mock对象)来创建以便测试的测试方法。2、为什么要进行Mock测试?Mock是为了解决不同的单元之…

  • 一阶倒立摆分析_倒立摆受力分析

    一阶倒立摆分析_倒立摆受力分析摆的运动是两种运动的叠加:1.平动,包含x方向和y方向。2.转动,转轴为质心。尽管物理上的转轴是其端点,但这个端点同时也是摆的受力点。在端点(非中心)施加垂直于摆臂的力,摆将绕其质心转动。  因为摆的重力作用于其转轴(质心),因此摆自身的重力对摆不施加力矩。这可以算作将质心作为转轴来分析的一个优势。   …

  • 外挂基础_开挂的正确姿势

    外挂基础_开挂的正确姿势一、前言  所谓游戏外挂,其实是一种游戏外辅程序,它可以协助玩家自动产生游戏动作、修改游戏网络数据包以及修改游戏内存数据等,以实现玩家用最少的时间和金钱去完成功力升级和过关斩将。虽然,现在对游戏外挂程序的“合法”身份众说纷纭,在这里我不想对此发表任何个人意见,让时间去

  • 手机发布版sha1怎么获取_androidstudio导出项目zip

    手机发布版sha1怎么获取_androidstudio导出项目zip申请key必须用发布版的SHA1及MD51.打包出来apk;2.将apk修改后缀为.rar文件后解压;3.进入解压后的META-INF目录,该目录下会存在文件CERT.RSA;4.在该目录下打开cmd,输入命令:keytool-printcert-fileCERT.RSA若提示输入密码,则输入android后回车…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号