- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
您好,我正在开展一个编写我们自己的霍夫曼编码的项目。我目前在将二进制 1 和 0 写入输出文件时遇到问题。它适用于较小的输入文件,但对于非常大的文件,它不会将任何内容写入输出文件。负责写入的方法是 compress
方法。任何帮助,将不胜感激。谢谢!
package proj3;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.PriorityQueue;
public class Project3 {
//variables for PriorityQueue and Huffman Tree
private static PriorityQueue<BinaryNode<Character>> queue;
private static BinaryNode<Character> huffTree;
private static Map<Character, String> table = new LinkedHashMap<Character, String>();
/**
* Method for creating Huffman Tree
* @param counts Map that contains all characters and their frequencies
* @return the Huffman Tree
*/
public static BinaryNode<Character> makeTree(Map<Character, Integer> counts)
{
queue = new PriorityQueue<BinaryNode<Character>>();
for(Character c : counts.keySet())
{
BinaryNode<Character> tree = new BinaryNode<Character>(c, counts.get(c), null, null);
queue.add(tree);
}
while(!queue.isEmpty())
{
if(queue.size() >= 2)
{
BinaryNode<Character> n1 = queue.remove();
BinaryNode<Character> n2 = queue.remove();
Integer weight = n1.getFreq() + n2.getFreq();
huffTree = new BinaryNode<Character>(null, weight, n1, n2);
queue.add(huffTree);
}
if(queue.size() == 1)
{
return queue.remove();
}
}
return huffTree;
}
public static void encode(BinaryNode<Character> node, String s)
{
if(!node.isLeaf())
{
encode(node.getLeft(), s + "0");
encode(node.getRight(), s + "1");
}
else
{
table.put(node.getElement(), s);
}
}
public static void compress(String in, String out) throws IOException
{
try
{
File outFile = new File(out);
FileOutputStream compressedFile = new FileOutputStream(outFile);
Scanner infile = new Scanner(new FileInputStream(in));
while(infile.hasNext())
{
infile.useDelimiter("");
String str = infile.next();
Character character = str.charAt(0);
for(Character c : table.keySet())
{
if(c == character){
compressedFile.write(table.get(c).getBytes());
compressedFile.flush();
}
}
}
for(Byte b : table.get('^').getBytes())
{
compressedFile.write(b);
}
infile.close();
compressedFile.close();
}
catch (FileNotFoundException e)
{
System.err.println("File not found.");
e.printStackTrace();
}
}
public static void decompress(String s)
{
}
public static void printEncodings(Map<Character, String> m)
{
ArrayList<Character> chars = new ArrayList<Character>();
System.out.println("Character Encodings");
System.out.println("---------------------");
for(Character c : m.keySet())
{
chars.add(c);
Collections.sort(chars);
}
for(Character c : chars)
{
System.out.print(c + "\t" + m.get(c) + "\n");
}
System.out.println();
System.out.println("Total Characters: " + chars.size());
}
/**
* Method for creating map with character and its frequencies
* @param s the file name to be opened
* @return the Map containing characters and frequencies
*/
public static Map<Character, Integer> charCount(String s){
Map<Character, Integer> counts = new LinkedHashMap<Character, Integer>();
ArrayList<Character> chars = new ArrayList<Character>();
try {
Scanner file = new Scanner(new FileInputStream(s));
while(file.hasNext()){
file.useDelimiter("");
String str = file.next();
Character c = str.charAt(0);
if(counts.containsKey(c)){
counts.put(c, counts.get(c) + 1);
}
else{
counts.put(c, 1);
}
}
counts.put('^', 1);
System.out.println("Character Frequencies");
System.out.println("---------------------");
for(Character c : counts.keySet())
{
chars.add(c);
Collections.sort(chars);
}
for(Character c : chars){
System.out.println(c + "\t" + counts.get(c));
}
System.out.println();
System.out.println("Total characters: " + chars.size() + "\n");
file.close();
}
catch (FileNotFoundException e) {
System.err.println("File not found.");
System.exit(0);
}
return counts;
}
public static void main(String[] args){
if(args.length != 3)
{
throw new IllegalArgumentException("Invalid number of arguments.");
}
encode(makeTree(charCount(args[0])), "");
printEncodings(table);
try {
compress(args[0], args[1]);
} catch (IOException e) {
e.printStackTrace();
}
}
}
最佳答案
我很确定您在 compress() 方法中遇到了性能/内存问题。编码在您的主要方法中打印正常,但我相信文件输出会卡住。我可以在您的代码中看到至少三种优化的可能性:
您正在使用Scanner逐字符读取输入文件,但不使用 Scanner 提供的任何解析功能。尝试使用 InputStreamReader相反。
您正在循环遍历霍夫曼表中的键集并检查是否相等。您可以简单地使用当前字符来获取它映射到的字符串并省略循环。
您无需循环字节数组即可将其写入输出文件。 FileOutputStream的write()方法可以将整个字节数组作为参数。
凭借我拙劣的 Java 技能,我宁愿以如下方式实现它;请注意,这是未经测试的代码,因为我没有您的 BinaryNode 类:
public static void compress(String in, String out) throws IOException
{
try
{
File outFile = new File(out);
FileOutputStream compressedFile = new FileOutputStream(outFile);
// 1. Use a Reader instead of a Scanner;
// make sure to use the correct charset
FileInputStream fis= new FileInputStream(in);
Reader reader = new InputStreamReader(fis,
Charset.forName("US-ASCII"));
// use BufferedReader for even better performance
Reader bufferedReader = new BufferedReader(reader);
int r;
while ((r = bufferedReader.read()) != -1) {
char ch= (char) r;
// 2. Get the string for this character directly instead of
// looping the keySet and checking for equivalence
String s= table.get(ch);
if (s != null) {
// 3. Write entire array of bytes instead of
// looping and writing bytes one by one
compressedFile.write(s.getBytes());
}
}
fis.close();
compressedFile.close();
}
...
关于java - 将大型二进制数据写入文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16256779/
我有这个代码 var myChart = new FusionCharts("../themes/clean/charts/hbullet.swf", "myChartId", "400", "75
既然写入是立即进行的(复制到内核缓冲区并返回),那么使用 io_submit 进行写入有什么好处? 事实上,它 (aio/io_submit) 看起来更糟,因为您必须在堆上分配写入缓冲区并且不能使用基
我正在使用 mootool 的 Request.JSON 从 Twitter 检索推文。收到它后,我将写入目标 div 的 .innerHTML 属性。当我在本地将其作为文件进行测试时,即 file:
最终,我想将 Vertica DB 中的数据抓取到 Spark 中,训练机器学习模型,进行预测,并将这些预测存储到另一个 Vertica DB 中。 当前的问题是确定流程最后部分的瓶颈:将 Spark
我使用 WEKA 库编写了一个 Java 程序, 训练分类算法 使用经过训练的算法对未标记的数据集运行预测 将结果写入 .csv 文件 问题在于它当前写出离散分类结果(即算法猜测一行属于哪个类别)。我
背景 - 我正在考虑使用 clickonce 通过 clickonce(通过网站)部署 WinForms 应用程序。相对简单的应用程序的要素是: - 它是一个可执行文件和一个数据库文件(sqlite)
是否有更好的解决方案来快速初始化 C 数组(在堆上创建)?就像我们使用大括号一样 double** matrix_multiply(const double **l_matrix, const dou
我正在读取 JSON 文件,取出值并进行一些更改。 基本上我向数组添加了一些值。之后我想将其写回到文件中。当我将 JSONArray 写回文件时,会被写入字符串而不是 JSONArray 对象。怎样才
我为两个应用程序使用嵌入式数据库,其中一个是服务器,另一个是客户端。客户端应用程序。可以向服务器端发送获取数据请求以检索数据并显示在表格(或其他)中。问题是这样的:如何将获取的数据保存(写入)到页面文
是否有更好的解决方案来快速初始化 C 数组(在堆上创建)?就像我们使用大括号一样 double** matrix_multiply(const double **l_matrix, const dou
从问题得出问题:找到所有 result = new ArrayList(); for (int i = 2; i >(i%8) & 0x1) == 0) { result.add(i
由于某种原因,它没有写入 CSV。谁能明白为什么它不写吗? def main(): list_of_emails = read_email_csv() #read input file, cr
关闭。 这个问题是 not reproducible or was caused by typos 。它目前不接受答案。 这个问题是由于错别字或无法再重现的问题引起的。虽然类似的问题可能在这里出现,
我目前正在开发一个保存和加载程序,但我无法获得正确的结果。 编写程序: #include #include #define FILENAME "Save" #define COUNT 6 type
import java.io.*; public class Main2 { public static void main(String[] args) throws Exception {
我需要使用预定义位置字符串“Office”从所有日历中检索所有 iOS 事件,然后将结果写入 NSLog 和 UITextView。 到目前为止,这是我的代码: #import "ViewCo
我正在尝试将 BOOL 值写入 PFInstallation 中的列,但会不停地崩溃: - (IBAction)pushSwitch:(id)sender { NSUserDefaults *push
我以前在学校学过一些简单的数据库编程,但现在我正在尝试学习最佳实践,因为我正在编写更复杂的应用程序。写入 MySQL 数据库并不难,但我想知道让分布式应用程序写入 Amazon EC2 上的远程数据库
是否可以写回到ResourceBundle?目前我正在使用 ResourceBundle 来存储信息,在运行时使用以下内容读取信息 while(ResourceBundle.getBundle("bu
关闭。这个问题是not reproducible or was caused by typos .它目前不接受答案。 这个问题是由于错别字或无法再重现的问题引起的。虽然类似的问题可能是on-topi
我是一名优秀的程序员,十分优秀!