NIO官方例子—正则表达式匹配和解码问题MalformedInputException

NIO的特性:

  1. Buffers for data of primitive types
  2. Character-set encoders and decoders
  3. A pattern-matching facility based on Perl-style regular expressions
  4. Channels, a new primitive I/O abstraction
  5. A file interface that supports locks and memory mapping
  6. A multiplexed, non-blocking I/O facility for writing scalable servers

很多书本上,一般只提到NIO的特性1、4、5,对特性2提及的也比较少,我看过的几本书上几本上没有提到特性3、6。特性6在网上到能搜到不少资料,socket的高级编程、MINA框架、Lucene框架中大量使用NIO。

 

 

最经查看NIO的官方API的时候,发现其官方NIO的第一个例子Grep.java中就有特性3的运用:

 

public class Grep {
	//16 位的 Unicode 代码单元序列和字节序列之间的命名映射关系。
    //此类定义了用于创建解码器和编码器以及检索与 charset 关联的各种名称的方法。
    // Charset and decoder for ISO-8859-15
    private static Charset charset = Charset.forName("UTF-8");//测试中文。。
    private static CharsetDecoder decoder = charset.newDecoder();

    // Pattern used to parse lines
    private static final Pattern linePattern = Pattern.compile(".*\r?\n");

    // The input pattern that we're looking for
    private static Pattern pattern; 

    // Compile the pattern from the command line
    private static void compile(String pat) {
	try {
	    pattern = Pattern.compile(pat);
	} catch (PatternSyntaxException x) {
	    System.err.println(x.getMessage());
	    System.exit(1);
	}
    }

    // Use the linePattern to break the given CharBuffer into lines, applying
    // the input pattern to each line to see if we have a match
    private static void grep(File f, CharBuffer cb) {
	Matcher lm = linePattern.matcher(cb);	// Line matcher
	Matcher pm = null;			// Pattern matcher
	int lines = 0;
	while (lm.find()) {
	    lines++;
	    CharSequence cs = lm.group(); 	// The current line
	    if (pm == null)
		pm = pattern.matcher(cs);
	    else
		pm.reset(cs);
	    if (pm.find())
		System.out.print(f + ":" + lines + ":" + cs);
	    if (lm.end() == cb.limit())
		break;
	}
    }

    // Search for occurrences of the input pattern in the given file
    //
    private static void grep(File f) throws IOException {

	// Open the file and then get a channel from the stream
	FileInputStream fis = new FileInputStream(f);
	FileChannel fc = fis.getChannel();

	// Get the file's size and then map it into memory
	int sz = (int)fc.size();
	MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, sz);

	// Decode the file into a char buffer
	CharBuffer cb = decoder.decode(bb);
	// Perform the search
	grep(f, cb);
	// Close the channel and the stream
	fc.close();
    }

    public static void main(String[] args) {
    	args = new String[]{"int","test.log"};
	if (args.length < 2) {
	    System.err.println("Usage: java Grep pattern file...");
	    return;
	}
	compile(args[0]);
	for (int i = 1; i < args.length; i++) {
	    File f = new File(args[i]);
	    try {
		grep(f);
	    } catch (IOException x) {
		System.err.println(f + ": " + x);
	    }
	}
    }

}

 

总结:

Grep.java使用正则表达式来封装分行,这样就可以实现BufferedReader的readLine()方法的功能。

使用这则匹配,可以查询匹配的行的内容,可以做日志查询的功能。

直接借助Charset类提供解码(字符解码),但是用上面的代码解码方式改造后,读文件超过10M就抛出java.nio.charset.MalformedInputException的异常。

 

public class MalformedInputException extends CharacterCodingException 当输入字节序列对于给定 charset 来说是不合法的,或者输入字符序列不是合法的 16 位 Unicode 序列时,抛出此经过检查的异常。

提出解决方案一:只是一个思路,与我这里的问题不符合,就没有深入研究。

        方案二描述:在处理大文本文件字符编码转换时碰到该问题,即使用CharsetDecoder.decode()方法解码一个MappedByteBuffer对象时,如果这个MappedByteBuffer对象的长度设置的不好,可能会出现“java.nio.charset.MalformedInputException:Malformed input length is N(N代表一个整数).”的错误。但是如果直接使用Charset.decode()方法,则不会出现这样的错误。

方案二解码成功,但是我测了个20M的文件就OutOfMemoryError。(20M只是我随便测试的一个值)

 

 

 

<!--EndFragment-->

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值