【Java】——常见问题03

版权声明:希望各位能遵守各自内心的原则 https://blog.csdn.net/weixin_40918067/article/details/81948617

【问题】需求如下:aaa1,aaa2...这一类代表的是名字,bbb1...代表是生日,ccc1....表示性别,现在需要讲aaa1...表示名字和ccc1这些表示性别的读出来,放入另一个.txt中;

读取之前数据如下 他们各个表示的类型有  ---  读取之后

          读取后变为由“,”分隔,读取的.txt文本比较大如果java堆栈不够,能不能分批读取完,再写入新.txt;能不能给我一段代码。

解答:

如下的程序,将一个行数为fileLines的文本文件平均分为splitNum个小文本文件,其中换行符'r'是linux上的,windows的java换行符是'\r\n':

package kddcup2012.task2.FileSystem;  
  
import java.io.BufferedInputStream;  
import java.io.BufferedReader;  
import java.io.File;  
import java.io.FileInputStream;  
import java.io.FileWriter;  
import java.io.IOException;  
import java.io.InputStreamReader;  
  
public class FileSplit  
{     
    public static void main(String[] args) throws IOException  
    {  
        long timer = System.currentTimeMillis();  
        int bufferSize = 20 * 1024 * 1024;//设读取文件的缓存为20MB   
          
        //建立缓冲文本输入流   
        File file = new File("/media/Data/毕业设计/kdd cup/数据/userid_profile.txt");  
        FileInputStream fileInputStream = new FileInputStream(file);  
        BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);  
        InputStreamReader inputStreamReader = new InputStreamReader(bufferedInputStream);  
        BufferedReader input = new BufferedReader(inputStreamReader, bufferSize);  
          
        int splitNum = 112-1;//要分割的块数减一   
        int fileLines = 23669283;//输入文件的行数   
        long perSplitLines = fileLines / splitNum;//每个块的行数   
        for (int i = 0; i <= splitNum; ++i)  
        {  
            //分割   
            //每个块建立一个输出   
            FileWriter output = new FileWriter("/home/haoqiong/part" + i + ".txt");  
            String line = null;  
            //逐行读取,逐行输出   
            for (long lineCounter = 0; lineCounter < perSplitLines && (line = input.readLine()) != null; ++lineCounter)  
            {  
                output.append(line + "\r");  
            }  
            output.flush();  
            output.close();  
            output = null;  
        }  
        input.close();  
        timer = System.currentTimeMillis() - timer;  
        System.out.println("处理时间:" + timer);  
    }  
}  

             以上程序处理大文本文件只需要30MB左右的内存空间(这和所设的读取缓冲大小有关),但是速度不是很快,在磁盘没有其他程序占用的情况下,将200MB文件分割为112份需要20秒(机器配置:Centrino2 P7450 CPU,2GB DDR3内存,Ubuntu 11.10系统,硬盘最大读写速度大约60MB/S)。

             另外,对于几百兆到2GB大小的文件,使用内存映射文件的话,速度会块一些,但是内存映射由于映射的文件长度不能超过java中int类型的最大值,所以只能处理2GB以下的文件。

java 读取一个巨大的文本文件既能保证内存不溢出又能保证性能;

package helloword.helloword;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

public class ReadBig {
    public static String fff = "C:\\mq\\read\\from.xml";

    public static void main1(String[] args) throws Exception {

        final int BUFFER_SIZE = 0x300000;// 缓冲区大小为3M

        File f = new File(fff);

        MappedByteBuffer inputBuffer = ne RandomAccessFile(f,"r").getChannel()
                                     .map(FileChannel.MapMode.READ_ONLY, f.length() / 2, f.length() / 2);

        byte[] dst = new byte[BUFFER_SIZE];// 每次读出3M的内容

        long start = System.currentTimeMillis();

        for (int offset = 0; offset < inputBuffer.capacity(); offset += BUFFER_SIZE) {

            if (inputBuffer.capacity() - offset >= BUFFER_SIZE) {

                for (int i = 0; i < BUFFER_SIZE; i++)

                    dst[i] = inputBuffer.get(offset + i);

            } else {

                for (int i = 0; i < inputBuffer.capacity() - offset; i++)

                    dst[i] = inputBuffer.get(offset + i);

            }

            int length = (inputBuffer.capacity() % BUFFER_SIZE == 0) ? BUFFER_SIZE
                    : inputBuffer.capacity() % BUFFER_SIZE;

            System.out.println(new String(dst, 0, length));// new
            // String(dst,0,length)这样可以取出缓存保存的字符串,可以对其进行操作

        }

        long end = System.currentTimeMillis();

        System.out.println("读取文件文件一半内容花费:" + (end - start) + "毫秒");

    }

    public static void main2(String[] args) throws Exception {
        int bufSize = 1024;
        byte[] bs = new byte[bufSize];
        ByteBuffer byteBuf = ByteBuffer.allocate(1024);
        FileChannel channel = new RandomAccessFile(fff, "r").getChannel();
        while (channel.read(byteBuf) != -1) {
            int size = byteBuf.position();
            byteBuf.rewind();
            byteBuf.get(bs); // 把文件当字符串处理,直接打印做为一个例子。
            System.out.print(new String(bs, 0, size));
            byteBuf.clear();
        }

    }

    public static void main3(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new FileReader(fff));
        String line = null;
        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }
    }

    public static void main(String[] args) throws Exception {
        int bufSize = 1024;
        byte[] bs = new byte[bufSize];
        ByteBuffer byteBuf = ByteBuffer.allocate(1024);
        FileChannel channel = new RandomAccessFile("d:\\filename", "r").getChannel();
        while (channel.read(byteBuf) != -1) {
            int size = byteBuf.position();
            byteBuf.rewind();
            byteBuf.get(bs);
            // 把文件当字符串处理,直接打印做为一个例子。
            System.out.print(new String(bs, 0, size));
            byteBuf.clear();
        }
    }

}
package helloword.helloword;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.util.Scanner;

public class TestPrint {
    public static void main(String[] args) throws IOException {
        String path = "你要读的文件的路径";
        RandomAccessFile br = new RandomAccessFile(path, "rw");// 这里rw看你了。要是之都就只写r
        String str = null, app = null;
        int i = 0;
        while ((str = br.readLine()) != null) {
            i++;
            app = app + str;
            if (i >= 100) {// 假设读取100行
                i = 0;
                // 这里你先对这100行操作,然后继续读
                app = null;
            }
        }
        br.close();
    }

    // 当逐行读写大于2G的文本文件时推荐使用以下代码
    void largeFileIO(String inputFile, String outputFile) {
        try {
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File(inputFile)));
            BufferedReader in = new BufferedReader(new InputStreamReader(bis, "utf-8"), 10 * 1024 * 1024);// 10M缓存
            FileWriter fw = new FileWriter(outputFile);
            while (in.ready()) {
                String line = in.readLine();
                fw.append(line + " ");
            }
            in.close();
            fw.flush();
            fw.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

java 读取大容量文件,内存溢出?怎么按几行读取,读取多次。 最佳答案

 

        jdk本身就支持超大文件的读写。

网上的文章基本分为两大类:

           一类是使用BufferedReader类读写超大文件;

          另一类是使用RandomAccessFile类读取,经过比较,最后使用了前一种方式进行超大文件的读取,下面是相关代码,其实很简单

File file = new File(filepath);   
BufferedInputStream fis = new BufferedInputStream(new FileInputStream(file));    
BufferedReader reader = new BufferedReader(new InputStreamReader(fis,"utf-8"),5*1024*1024);// 用5M的缓冲读取文本文件  
  
String line = "";
while((line = reader.readLine()) != null){
   //TODO: write your business
}

注意代码,在实例化BufferedReader时,增加一个分配缓存的参数即可

【题目】System是一个类,为啥不像scanner一样要创建一个对象才可以用,直接就System.out.println() ?还有new Scanner(System.in) 这个括号里可以填System.in以外的东西吗 ,不然为什么要设计这么一大串?感觉还是c++方便 cin cout 写3,4个字母就没了;

解答:

1、因为在Java 里有一个静态(static)方法的概念,且静态方法也就是类的方法,不需要创建对象 ,也就可以引用了;例如许多工具类方法为了 调用方便就定义成“静态方法“。

2、还有Java语法的特点就是冗长,所以现在JavaScript这种脚本语言或者Scala函数式的语言受到很多青睐;

3、而System.in就是一个输入流的引用而已,你可以在这里填任何输入流实例的引用来初始化Scanner。因为System.in比较特殊,而且比较常用(标准输入),因此才设置为默认值;

4、推荐 Core Java Java核心技术基础部分看看。 然后可以下载一下JDK 去阅读一下System类的源码,都是概念性的东西,比较简单

猜你喜欢

转载自blog.csdn.net/weixin_40918067/article/details/81948617