Java를 사용하여 일련의 이진 파일에서 검색해야하는 바이트 시퀀스가 있습니다.Java가있는 이진 파일에서 바이트 시퀀스 검색
예 : 바이너리 파일에서 바이트 시퀀스 DEADBEEF
(16 진수)을 찾고 있습니다. Java에서이 작업을 수행하려면 어떻게해야합니까? 바이너리 파일에 대해 String.contains()
과 같은 내장 메소드가 있습니까?
Java를 사용하여 일련의 이진 파일에서 검색해야하는 바이트 시퀀스가 있습니다.Java가있는 이진 파일에서 바이트 시퀀스 검색
예 : 바이너리 파일에서 바이트 시퀀스 DEADBEEF
(16 진수)을 찾고 있습니다. Java에서이 작업을 수행하려면 어떻게해야합니까? 바이너리 파일에 대해 String.contains()
과 같은 내장 메소드가 있습니까?
아니요, 이렇게하는 기본 제공 방법이 없습니다. 그러나, 직접 HERE에서 복사 (원본 코드에 적용이 수정 프로그램) : 라이브러리를 선호하는 사람들을 위해
/**
* Knuth-Morris-Pratt Algorithm for Pattern Matching
*/
class KMPMatch {
/**
* Finds the first occurrence of the pattern in the text.
*/
public int indexOf(byte[] data, byte[] pattern) {
int[] failure = computeFailure(pattern);
int j = 0;
if (data.length == 0) return -1;
for (int i = 0; i < data.length; i++) {
while (j > 0 && pattern[j] != data[i]) {
j = failure[j - 1];
}
if (pattern[j] == data[i]) { j++; }
if (j == pattern.length) {
return i - pattern.length + 1;
}
}
return -1;
}
/**
* Computes the failure function using a boot-strapping process,
* where the pattern is matched against itself.
*/
private int[] computeFailure(byte[] pattern) {
int[] failure = new int[pattern.length];
int j = 0;
for (int i = 1; i < pattern.length; i++) {
while (j > 0 && pattern[j] != pattern[i]) {
j = failure[j - 1];
}
if (pattern[j] == pattern[i]) {
j++;
}
failure[i] = j;
}
return failure;
}
}
private int bytesIndexOf(byte[] source, byte[] search, int fromIndex) {
boolean find = false;
int i;
for (i = fromIndex; i < (source.length - search.length); i++) {
if (source[i] == search[0]) {
find = true;
for (int j = 0; j < search.length; j++) {
if (source[i + j] != search[j]) {
find = false;
}
}
}
if (find) {
break;
}
}
if (!find) {
return -1;
}
return i;
}
문자열의 마지막 바이트에서 작동하지 않습니다. –
'
, 구현은 크 누스 - 모리스 - 프랫 알고리즘 (아래 소스)에있다 트위터의 Elephant-Bird 오픈 소스 라이브러리 (Apache 라이센스). 당신은 bigdoc를 사용하여 기가 바이트 순서 파일에서 바이트의 순서를 찾을 수 https://github.com/twitter/elephant-bird
package com.twitter.elephantbird.util;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
/**
* An efficient stream searching class based on the Knuth-Morris-Pratt algorithm.
* For more on the algorithm works see: http://www.inf.fh-flensburg.de/lang/algorithmen/pattern/kmpen.htm.
*/
public class StreamSearcher {
protected byte[] pattern_;
protected int[] borders_;
// An upper bound on pattern length for searching. Throws exception on longer patterns
public static final int MAX_PATTERN_LENGTH = 1024;
public StreamSearcher(byte[] pattern) {
setPattern(pattern);
}
/**
* Sets a new pattern for this StreamSearcher to use.
* @param pattern
* the pattern the StreamSearcher will look for in future calls to search(...)
*/
public void setPattern(byte[] pattern) {
if (pattern.length > MAX_PATTERN_LENGTH) {
throw new IllegalArgumentException("The maximum pattern length is " + MAX_PATTERN_LENGTH);
}
pattern_ = Arrays.copyOf(pattern, pattern.length);
borders_ = new int[pattern_.length + 1];
preProcess();
}
/**
* Searches for the next occurrence of the pattern in the stream, starting from the current stream position. Note
* that the position of the stream is changed. If a match is found, the stream points to the end of the match -- i.e. the
* byte AFTER the pattern. Else, the stream is entirely consumed. The latter is because InputStream semantics make it difficult to have
* another reasonable default, i.e. leave the stream unchanged.
*
* @return bytes consumed if found, -1 otherwise.
* @throws IOException
*/
public long search(InputStream stream) throws IOException {
long bytesRead = 0;
int b;
int j = 0;
while ((b = stream.read()) != -1) {
bytesRead++;
while (j >= 0 && (byte)b != pattern_[j]) {
j = borders_[j];
}
// Move to the next character in the pattern.
++j;
// If we've matched up to the full pattern length, we found it. Return,
// which will automatically save our position in the InputStream at the point immediately
// following the pattern match.
if (j == pattern_.length) {
return bytesRead;
}
}
// No dice, Note that the stream is now completely consumed.
return -1;
}
/**
* Builds up a table of longest "borders" for each prefix of the pattern to find. This table is stored internally
* and aids in implementation of the Knuth-Moore-Pratt string search.
* <p>
* For more information, see: http://www.inf.fh-flensburg.de/lang/algorithmen/pattern/kmpen.htm.
*/
protected void preProcess() {
int i = 0;
int j = -1;
borders_[i] = j;
while (i < pattern_.length) {
while (j >= 0 && pattern_[i] != pattern_[j]) {
j = borders_[j];
}
borders_[++i] = ++j;
}
}
}
사용하지 않은 MAX_PATTERN_LENGTH 멤버가 나타내는 패턴에 1024 바이트 제한을 두어야 할 부분은 무엇입니까? – user1767316
:
당신은 Github에서의 라이브러리를 찾을 수 있습니다.
여기 Github에서에에서 해방 및 예 : https://github.com/riversun/bigdoc
package org.example;
import java.io.File;
import java.util.List;
import org.riversun.bigdoc.bin.BigFileSearcher;
public class Example {
public static void main(String[] args) throws Exception {
byte[] searchBytes = "hello world.".getBytes("UTF-8");
File file = new File("/var/tmp/yourBigfile.bin");
BigFileSearcher searcher = new BigFileSearcher();
List<Long> findList = searcher.searchBigFile(file, searchBytes);
System.out.println("positions = " + findList);
}
}
당신이 메모리를 검색 할 경우,이를 확인. 여기 Github의 상에 예 : https://github.com/riversun/finbin
import java.util.List;
import org.riversun.finbin.BigBinarySearcher;
public class Example {
public static void main(String[] args) throws Exception {
BigBinarySearcher bbs = new BigBinarySearcher();
byte[] iamBigSrcBytes = "Hello world.It's a small world.".getBytes("utf-8");
byte[] searchBytes = "world".getBytes("utf-8");
List<Integer> indexList = bbs.searchBytes(iamBigSrcBytes, searchBytes);
System.out.println("indexList=" + indexList);
}
}
반환 바이트
의 배열의 모든 일치하는 위치는 또한
I에 유래 사랑 바이트 :)의 큰 배열을 견딜 수 있습니다. 감사! – Teekin
거의 최적화 : data.length가 0 인 경우 패턴의 실패 함수를 계산할 필요가 없습니다. ==> data.length 제로 검사를 함수의 첫 번째 행으로 이동할 수 있습니다. – dexametason