mirror of
https://github.com/revanced/ARSCLib.git
synced 2025-05-03 07:34:25 +02:00
improve input stream read performance
This commit is contained in:
parent
2c9c0d1ba6
commit
74aba3d8ff
@ -16,7 +16,6 @@
|
||||
package com.reandroid.lib.arsc.chunk;
|
||||
|
||||
import com.reandroid.lib.arsc.header.HeaderBlock;
|
||||
import com.reandroid.lib.arsc.io.BlockReader;
|
||||
import com.reandroid.lib.arsc.item.ByteArray;
|
||||
|
||||
import java.io.*;
|
||||
@ -26,30 +25,25 @@ package com.reandroid.lib.arsc.chunk;
|
||||
* handle any future android changes
|
||||
* */
|
||||
public class UnknownChunk extends BaseChunk implements HeaderBlock.HeaderLoaded {
|
||||
private final ByteArray headerExtra;
|
||||
private final ByteArray body;
|
||||
public UnknownChunk() {
|
||||
super(INITIAL_CHUNK_TYPE, 1);
|
||||
this.headerExtra = new ByteArray();
|
||||
this.body = new ByteArray();
|
||||
|
||||
addToHeader(this.headerExtra);
|
||||
addChild(body);
|
||||
|
||||
setHeaderLoaded(this);
|
||||
}
|
||||
public ByteArray getBody(){
|
||||
return body;
|
||||
}
|
||||
@Override
|
||||
public void onChunkTypeLoaded(short type) {
|
||||
}
|
||||
@Override
|
||||
public void onHeaderSizeLoaded(int headerSize) {
|
||||
int extraSize = headerSize - 8;
|
||||
this.headerExtra.setSize(extraSize);
|
||||
}
|
||||
@Override
|
||||
public void onChunkSizeLoaded(int headerSize, int chunkSize) {
|
||||
int bodySize = chunkSize - headerSize;
|
||||
this.body.setSize(bodySize);
|
||||
getBody().setSize(chunkSize - headerSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -68,18 +62,25 @@ public class UnknownChunk extends BaseChunk implements HeaderBlock.HeaderLoaded
|
||||
}
|
||||
return os.toByteArray();
|
||||
}
|
||||
public void readBytes(File file) throws IOException{
|
||||
BlockReader reader=new BlockReader(file);
|
||||
super.readBytes(reader);
|
||||
public int readBytes(File file) throws IOException{
|
||||
FileInputStream inputStream=new FileInputStream(file);
|
||||
int result=readBytes(inputStream);
|
||||
inputStream.close();
|
||||
return result;
|
||||
}
|
||||
public void readBytes(InputStream inputStream) throws IOException{
|
||||
BlockReader reader=new BlockReader(inputStream);
|
||||
super.readBytes(reader);
|
||||
public int readBytes(InputStream inputStream) throws IOException{
|
||||
int result;
|
||||
result=getHeaderBlock().readBytes(inputStream);
|
||||
result+=getBody().readBytes(inputStream);
|
||||
super.notifyBlockLoad();
|
||||
return result;
|
||||
}
|
||||
public final int writeBytes(File file) throws IOException{
|
||||
File dir=file.getParentFile();
|
||||
if(dir!=null && !dir.exists()){
|
||||
dir.mkdirs();
|
||||
if(dir.mkdirs()){
|
||||
throw new IOException("Can not create directory: "+dir);
|
||||
}
|
||||
}
|
||||
OutputStream outputStream=new FileOutputStream(file);
|
||||
int length = super.writeBytes(outputStream);
|
||||
@ -88,15 +89,10 @@ public class UnknownChunk extends BaseChunk implements HeaderBlock.HeaderLoaded
|
||||
}
|
||||
@Override
|
||||
public String toString(){
|
||||
HeaderBlock headerBlock = getHeaderBlock();
|
||||
return getClass().getSimpleName()
|
||||
+"{ type="+String.format("0x%04x", headerBlock.getType())
|
||||
+", chunkSize="+headerBlock.getChunkSize()
|
||||
+", headerExtra="+headerExtra.size()
|
||||
+", body="+body.size()+"}";
|
||||
return getHeaderBlock()
|
||||
+" {Body="+getBody().size()+"}";
|
||||
}
|
||||
|
||||
// This value must not exist is ChunkType enum list
|
||||
private static final short INITIAL_CHUNK_TYPE = 0x0207;
|
||||
private static final short INITIAL_CHUNK_TYPE = 0x0000;
|
||||
|
||||
}
|
||||
|
@ -15,55 +15,12 @@
|
||||
*/
|
||||
package com.reandroid.lib.arsc.header;
|
||||
|
||||
import com.reandroid.lib.arsc.base.Block;
|
||||
import com.reandroid.lib.arsc.chunk.ChunkType;
|
||||
import com.reandroid.lib.arsc.item.BlockItem;
|
||||
import com.reandroid.lib.arsc.item.ByteArray;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**No importance of this class, to be removed latter*/
|
||||
@Deprecated
|
||||
public class AnyHeader extends HeaderBlock{
|
||||
public AnyHeader() {
|
||||
super(ChunkType.NULL.ID);
|
||||
}
|
||||
public int readBytes(InputStream inputStream) throws IOException {
|
||||
int result=0;
|
||||
Block[] childes = getChildes();
|
||||
for(Block child:childes){
|
||||
if(child instanceof BlockItem){
|
||||
BlockItem blockItem=(BlockItem) child;
|
||||
result += blockItem.readBytes(inputStream);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public byte[] readChunkBytes(InputStream inputStream) throws IOException{
|
||||
int chunkSize = getChunkSize();
|
||||
int headerSize = getHeaderSize();
|
||||
if(chunkSize < 0 || chunkSize < headerSize){
|
||||
throw new IOException("Invalid chunk size: " + super.toString());
|
||||
}
|
||||
byte[] buffer = new byte[chunkSize];
|
||||
int length = chunkSize - headerSize;
|
||||
int offset = loadHeaderBytes(buffer);
|
||||
while (length>0){
|
||||
int len = inputStream.read(buffer, offset, length);
|
||||
length=length-len;
|
||||
offset=offset+len;
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
private int loadHeaderBytes(byte[] buffer){
|
||||
int index=0;
|
||||
Block[] childes = getChildes();
|
||||
for(Block child:childes){
|
||||
byte[] childBytes=child.getBytes();
|
||||
for(int i=0;i<childBytes.length;i++){
|
||||
buffer[index]=childBytes[i];
|
||||
index++;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
@ -15,16 +15,23 @@
|
||||
*/
|
||||
package com.reandroid.lib.arsc.header;
|
||||
|
||||
import com.reandroid.lib.arsc.base.BlockContainer;
|
||||
import com.reandroid.lib.arsc.chunk.ChunkType;
|
||||
import com.reandroid.lib.arsc.base.Block;
|
||||
import com.reandroid.lib.arsc.container.BlockList;
|
||||
import com.reandroid.lib.arsc.container.ExpandableBlockContainer;
|
||||
import com.reandroid.lib.arsc.io.BlockLoad;
|
||||
import com.reandroid.lib.arsc.io.BlockReader;
|
||||
import com.reandroid.lib.arsc.item.BlockItem;
|
||||
import com.reandroid.lib.arsc.item.ByteArray;
|
||||
import com.reandroid.lib.arsc.item.IntegerItem;
|
||||
import com.reandroid.lib.arsc.item.ShortItem;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
public class HeaderBlock extends ExpandableBlockContainer implements BlockLoad {
|
||||
private final ShortItem mType;
|
||||
@ -99,6 +106,46 @@ import java.io.IOException;
|
||||
int count=parent.countBytes();
|
||||
setChunkSize(count);
|
||||
}
|
||||
/**Non buffering reader*/
|
||||
public int readBytes(InputStream inputStream) throws IOException{
|
||||
int result = onReadBytes(inputStream);
|
||||
super.notifyBlockLoad();
|
||||
return result;
|
||||
}
|
||||
private int onReadBytes(InputStream inputStream) throws IOException {
|
||||
int readCount = readBytes(inputStream, this);
|
||||
int difference = getHeaderSize() - readCount;
|
||||
if(difference==0){
|
||||
return readCount;
|
||||
}
|
||||
if(extraBytes.getParent()==null){
|
||||
addChild(extraBytes);
|
||||
}
|
||||
extraBytes.setSize(difference);
|
||||
readCount += extraBytes.readBytes(inputStream);
|
||||
return readCount;
|
||||
}
|
||||
private int readBytes(InputStream inputStream, Block block) throws IOException{
|
||||
int result=0;
|
||||
if(block instanceof BlockItem){
|
||||
result = ((BlockItem)block).readBytes(inputStream);
|
||||
}else if(block instanceof BlockList){
|
||||
List<? extends Block> childes=
|
||||
((BlockList<? extends Block>) block).getChildes();
|
||||
for(Block child:childes){
|
||||
result+=readBytes(inputStream, child);
|
||||
}
|
||||
}else if(block instanceof BlockContainer){
|
||||
Block[] childes =
|
||||
((BlockContainer<? extends Block>) block).getChildes();
|
||||
for(Block child:childes){
|
||||
result+=readBytes(inputStream, child);
|
||||
}
|
||||
}else {
|
||||
throw new IOException("Can not read block type: "+block.getClass());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public void onReadBytes(BlockReader reader) throws IOException {
|
||||
int start=reader.getPosition();
|
||||
@ -155,14 +202,14 @@ import java.io.IOException;
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
short t= getType();
|
||||
ChunkType type= ChunkType.get(t);
|
||||
StringBuilder builder=new StringBuilder();
|
||||
short t = getType();
|
||||
ChunkType type = ChunkType.get(t);
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if(type!=null){
|
||||
builder.append(type.toString());
|
||||
}else {
|
||||
builder.append("Unknown type=");
|
||||
builder.append(String.format("0x%02x", ((int)t)));
|
||||
builder.append(String.format("0x%02x", (0xffff & t)));
|
||||
}
|
||||
builder.append("{Header=");
|
||||
builder.append(getHeaderSize());
|
||||
@ -172,6 +219,18 @@ import java.io.IOException;
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public static HeaderBlock readHeaderBlock(File file) throws IOException{
|
||||
InputStream inputStream = new FileInputStream(file);
|
||||
HeaderBlock headerBlock = readHeaderBlock(inputStream);
|
||||
inputStream.close();
|
||||
return headerBlock;
|
||||
}
|
||||
public static HeaderBlock readHeaderBlock(InputStream inputStream) throws IOException {
|
||||
HeaderBlock headerBlock=new HeaderBlock(ChunkType.NULL.ID);
|
||||
headerBlock.readBytes(inputStream);
|
||||
return headerBlock;
|
||||
}
|
||||
|
||||
public interface HeaderLoaded{
|
||||
void onChunkTypeLoaded(short type);
|
||||
void onHeaderSizeLoaded(int headerSize);
|
||||
|
@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.reandroid.lib.arsc.io;
|
||||
|
||||
import com.reandroid.lib.arsc.header.AnyHeader;
|
||||
import com.reandroid.lib.arsc.header.HeaderBlock;
|
||||
|
||||
import java.io.*;
|
||||
@ -309,15 +308,10 @@ import java.io.*;
|
||||
}
|
||||
return buff;
|
||||
}
|
||||
public static AnyHeader readHeaderBlock(File file) throws IOException{
|
||||
InputStream inputStream=new FileInputStream(file);
|
||||
AnyHeader anyHeader = readHeaderBlock(inputStream);
|
||||
inputStream.close();
|
||||
return anyHeader;
|
||||
public static HeaderBlock readHeaderBlock(File file) throws IOException{
|
||||
return HeaderBlock.readHeaderBlock(file);
|
||||
}
|
||||
public static AnyHeader readHeaderBlock(InputStream inputStream) throws IOException{
|
||||
AnyHeader anyHeader=new AnyHeader();
|
||||
anyHeader.readBytes(inputStream);
|
||||
return anyHeader;
|
||||
public static HeaderBlock readHeaderBlock(InputStream inputStream) throws IOException{
|
||||
return HeaderBlock.readHeaderBlock(inputStream);
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,8 @@ package com.reandroid.lib.arsc.pool;
|
||||
import com.reandroid.lib.arsc.array.StringArray;
|
||||
import com.reandroid.lib.arsc.array.TableStringArray;
|
||||
import com.reandroid.lib.arsc.chunk.ChunkType;
|
||||
import com.reandroid.lib.arsc.header.AnyHeader;
|
||||
import com.reandroid.lib.arsc.chunk.UnknownChunk;
|
||||
import com.reandroid.lib.arsc.header.HeaderBlock;
|
||||
import com.reandroid.lib.arsc.io.BlockReader;
|
||||
import com.reandroid.lib.arsc.item.IntegerArray;
|
||||
import com.reandroid.lib.arsc.item.IntegerItem;
|
||||
@ -57,19 +58,21 @@ import java.io.InputStream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads string pool from table block (resources.arsc)
|
||||
* Loads string pool only from table block (resources.arsc) without
|
||||
* loading other chunks
|
||||
*/
|
||||
public static TableStringPool readFromTable(InputStream inputStream) throws IOException {
|
||||
AnyHeader tableHeader = BlockReader.readHeaderBlock(inputStream);
|
||||
HeaderBlock tableHeader = HeaderBlock.readHeaderBlock(inputStream);
|
||||
if(tableHeader.getChunkType()!=ChunkType.TABLE){
|
||||
throw new IOException("Not TableBlock: "+tableHeader);
|
||||
}
|
||||
AnyHeader poolHeader = BlockReader.readHeaderBlock(inputStream);
|
||||
UnknownChunk poolChunk = new UnknownChunk();
|
||||
poolChunk.readBytes(inputStream);
|
||||
HeaderBlock poolHeader = poolChunk.getHeaderBlock();
|
||||
if(poolHeader.getChunkType()!=ChunkType.STRING){
|
||||
throw new IOException("Not StringPool: "+poolHeader);
|
||||
throw new IOException("Not StringPool chunk: " + poolChunk);
|
||||
}
|
||||
byte[] poolBytes = poolHeader.readChunkBytes(inputStream);
|
||||
BlockReader blockReader = new BlockReader(poolBytes);
|
||||
BlockReader blockReader = new BlockReader(poolChunk.getBytes());
|
||||
TableStringPool stringPool = new TableStringPool(true);
|
||||
stringPool.readBytes(blockReader);
|
||||
blockReader.close();
|
||||
|
Loading…
x
Reference in New Issue
Block a user