I have this method in Java and I want to improve it.
The method is used to replace some part (at the beginning, in the middle or at the end) of some File with the new bytes (the selected part can be replaced by less or more bytes).
The selection is done, by position(start) and quantity.
I can't to use external libraries (guava, or some other).
Here my old code:
public static void replaceBytesFile(RandomAccessFile rafTarget,
byte[] replacers, int start, int quantity) {
//replaces exact amount of bytes of a file starting at a specified position
RandomAccessFile rafTemp = null;
//Ini Select a Random NonExistent File
File userDirectory = new File(System.getProperty("user.dir"));
File temporalFile;
boolean existsTemporalFile = false;
String temporalFilename = "";
while (!existsTemporalFile) {
temporalFilename = "File_" + Double.toString(100000 * Math.random()) + ".tmp";
temporalFilename = userDirectory + MethodGen.FS + temporalFilename;
temporalFile = new File(temporalFilename);
if (!temporalFile.exists()) {
existsTemporalFile = true;
}
}
//End Select a Random NonExistent File
try {
rafTemp = new RandomAccessFile(temporalFilename, "rw");
int workBufferSize = 65536;
//Ini Copy first (Start - 1) MethodBytes
int step = workBufferSize;
int countPosition = 0;
while (countPosition < start) {
rafTarget.seek(countPosition);
rafTemp.seek(countPosition);
if ((start - countPosition) < step) {
step = start - countPosition;
}
byte[] WorkBuffer = new byte[step];
rafTarget.read(WorkBuffer);
rafTemp.write(WorkBuffer);
countPosition += step;
}
//End Copy first (start - 1) MethodBytes
rafTemp.write(replacers);
rafTarget.seek(start + quantity);
int end = (int) rafTarget.length();
//Ini Copy last MethodBytes
step = workBufferSize;
countPosition = start + quantity;
while (countPosition < end) {
rafTarget.seek(countPosition);
rafTemp.seek(countPosition - quantity + replacers.length);
if ((end - countPosition) <= step) {
step = end - countPosition;
}
byte[] WorkBuffer = new byte[step];
rafTarget.read(WorkBuffer);
rafTemp.write(WorkBuffer);
countPosition += step;
}
//End Copy last MethodBytes
rafTarget.setLength(0);
step = workBufferSize;
countPosition = 0;
end = (int) rafTemp.length();
//Ini Copy all MethodBytes to original
while (countPosition < end) {
rafTemp.seek(countPosition);
rafTarget.seek(countPosition);
if ((end - countPosition) <= step) {
step = end - countPosition;
}
byte[] WorkBuffer = new byte[step];
rafTemp.read(WorkBuffer);
rafTarget.write(WorkBuffer);
countPosition += step;
}
//End Copy all MethodBytes to original
rafTemp.close();
temporalFile = new File(temporalFilename);
temporalFile.delete();
} catch (IOException ioe) {
System.out.println(ioe.toString());
} finally {
try {
if (rafTemp != null) {
rafTemp.close();
}
} catch (IOException e) {
}
}
}
I'm copying manually in from original file to temporal file where the changes are performed, later ,
My code is working, but I want to know some best alternative in Java 8 (preferred).
Now How is test?
public static void main(String[] args) {
String originalFilename = "OriginalTraveling.txt";
String copiedFilename = "TravelingToBeChanged.txt";
Path copiedPath = Paths.get(copiedFilename);
Path originalPath = new File(originalFilename).toPath();
System.out.println("filename:" + originalFilename);
String contet = "I want to travel to my Country.";
try {
RandomAccessFile raf = new RandomAccessFile(originalFilename, "rw");
putBytesFile(raf, contet.getBytes(), 0);
Files.copy(originalPath, copiedPath, StandardCopyOption.REPLACE_EXISTING);
}
catch (IOException e) {
System.out.println("Exception caught " + e.toString());
}
try {
RandomAccessFile raf = new RandomAccessFile(copiedFilename, "rw");
String toBeChanged = "my Country.";
String toBeInserted = "India, China, Europe, Latin America, Australia.";
int position = contet.indexOf(toBeChanged);
replaceBytesFile(raf, toBeInserted.getBytes(), position, toBeChanged.length());
}
catch (IOException e) {
System.out.println("Exception caught " + e.toString());
}
try {
RandomAccessFile raf = new RandomAccessFile(copiedFilename, "rw");
String replacedContent = new String(getBytesFile(raf, 0, (int) raf.length()));
String toBeChanged = "Latin America";
String toBeInserted = "Colombia";
int position = replacedContent.indexOf(toBeChanged);
replaceBytesFile(raf, toBeInserted.getBytes(), position, toBeChanged.length());
} catch (IOException e) {
System.out.println("Exception caught " + e.toString());
}
}
Method to put Bytes!
public static void putBytesFile(RandomAccessFile RAFTarget, byte[] content, int position) {
int size = content.length;
try {
long oldPosition = RAFTarget.getFilePointer();
if (!((position < 0) || !(size > 0))) {
RAFTarget.seek(position);
RAFTarget.write(content);
RAFTarget.seek(oldPosition);
}
} catch (java.io.IOException e) {
System.out.println(e.toString());
}
}
Method Get Files!
public static byte[] getBytesFile(RandomAccessFile RAFSource, int position, int quantity) {
byte[] content = null;
try {
long oldPosition = RAFSource.getFilePointer();
if ((position < 0) || !(quantity > 0)) {
return (content);
} else {
if (RAFSource.length() < (position + quantity)) {
quantity = (int) RAFSource.length() - position;
}
RAFSource.seek(position);
content = new byte[quantity];
RAFSource.read(content);
RAFSource.seek(oldPosition);
}
} catch (java.io.IOException e) {
System.out.println(e.toString());
}
return content;
}
Content of OriginalTraveling.txt
I want to travel to my Country.
Content of TravelingToBeChanged.txt
I want to travel to India, China, Europe, Latin America, Australia.
Finally the Content of TravelingToBeChanged.txt
I want to travel to India, China, Europe, Colombia, Australia.
If it can be noticed, they are NOT changed by the same number of bytes.
Do you know some alternative to replace contents of File?
Even for ancient code, this looks unnecessary complicated.
E.g. instead of
//Ini Select a Random NonExistent File
File userDirectory = new File(System.getProperty("user.dir"));
File temporalFile;
boolean existsTemporalFile = false;
String temporalFilename = "";
while (!existsTemporalFile) {
temporalFilename = "File_" + Double.toString(100000 * Math.random()) + ".tmp";
temporalFilename = userDirectory + MethodGen.FS + temporalFilename;
temporalFile = new File(temporalFilename);
if (!temporalFile.exists()) {
existsTemporalFile = true;
}
}
just use
File temporalFile = File.createTempFile("File_", ".tmp", userDirectory);
See createTempFile
Further, instead of
int step = workBufferSize;
int countPosition = 0;
while (countPosition < start) {
rafTarget.seek(countPosition);
rafTemp.seek(countPosition);
if ((start - countPosition) < step) {
step = start - countPosition;
}
byte[] WorkBuffer = new byte[step];
rafTarget.read(WorkBuffer);
rafTemp.write(WorkBuffer);
countPosition += step;
}
Use
for(int step=workBufferSize, countPosition=0; countPosition < start; countPosition += step){
rafTarget.seek(countPosition);
rafTemp.seek(countPosition);
if ((start - countPosition) < step) {
step = start - countPosition;
}
byte[] WorkBuffer = new byte[step];
rafTarget.read(WorkBuffer);
rafTemp.write(WorkBuffer);
}
As you clearly have an initial statement, a condition and an increment operation, in other words, a typical for loop. The same applies to the other two while loops.
However, with newer APIs, things are much simpler anyway:
// consider using long for position and Path for the file, unless
// the RandomAccessFile is really needed for other purposes
public static void replaceBytesFile(RandomAccessFile rafTarget,
byte[] replacers, int start, int quantity) throws IOException {
// no need to force a particular directory for the temp file
Path tmp = Files.createTempFile("File_", ".tmp");
// use import static java.nio.file.StandardOpenOption.*;
// try( ... ) closes automatically, perfect for a temp file with DELETE_ON_CLOSE
try(FileChannel tmpCh = FileChannel.open(tmp, READ, WRITE, DELETE_ON_CLOSE)) {
// closing the target channel would also close rafTarget RandomAccessFile
FileChannel target = rafTarget.getChannel();
// just keep the data before start position, only copy remainder
long retainStart = start + (long)quantity, toCopy = target.size() - retainStart;
target.transferTo(retainStart, toCopy, tmpCh);
// write the replacement
target.write(ByteBuffer.wrap(replacers), start);
// copy back the remainder, to the new position
tmpCh.position(0);
target.transferFrom(tmpCh, start + (long)replacers.length, toCopy);
// adapt the length if necessary
target.truncate(start + toCopy + replacers.length);
}
}
Related
I am using RocksDB JNI and I found that reads are getting exponentially slow for this program
Initially, it's in an acceptable range. But when the program runs so that the total records reach 1 million then the read time logger prints are showing around 200-300 ms. Getting still worse, as the program runs. Am I using the JNI wrong?
long n = 0;
int counter = 0;
try(
final Options options = new Options()
.setCreateIfMissing(true)
.setComparator(new Comparator(new ComparatorOptions()){
#Override
public String name() {
return "default";
}
#Override
public int compare(final Slice a, final Slice b) {
long x = ByteBuffer.wrap(a.data()).getLong();
long y = ByteBuffer.wrap(b.data()).getLong();
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
})
.setWriteBufferSize(64 * SizeUnit.MB)
.setMaxWriteBufferNumber(6)
.setMinWriteBufferNumberToMerge(2);
final RocksDB db = RocksDB.open(options, "/PathToDB/")){
boolean loop = true;
while(loop) {
if(n == Long.MAX_VALUE){
loop = false;
}
for (int j=0;j<4;j++){
try(WriteBatch writeBatch = new WriteBatch()) {
for (int i = 0; i < 200; i++) {
String urlStr = "dummy"+counter;
counter++;
Long score = getScore(urlStr);
ByteBuffer buf = ByteBuffer.allocate(Long.BYTES);
buf.putLong(score);
writeBatch.put( buf.array() , urlStr.getBytes(UTF_8));
}
long st = System.currentTimeMillis();
db.write(new WriteOptions(), writeBatch);
long et = System.currentTimeMillis();
logger.logMessage(Test.class.getName(), Level.INFO, "RocksDB write of 200 URLs successful. Time taken - {0}", new Object[]{ et-st});
} catch (RocksDBException ex) {
}
}
byte[] firstKey = null, lastKey = null;
int readC = 0;
long st = System.currentTimeMillis();
final RocksIterator it = db.newIterator();
it.seekToFirst();
while(it.isValid() && readC < 50){
lastKey = it.key();
if(firstKey == null){
firstKey = lastKey;
}
it.next();
readC++;
}
long et = System.currentTimeMillis();
logger.logMessage(Test.class.getName(), Level.INFO, "RocksDB read of 50 URLs successful. Time taken - {0}", new Object[]{ et-st});
if(lastKey != null){
db.deleteRange(firstKey, lastKey);
}
n++;
}
}catch (Exception e){
logger.logMessage(Level.SEVERE, Test.class.getName(), e);
}
I tried to get a grasp of image rendering performance and created some code which draws full screen images using mutable images and PNGs.
The code runs fine in the simulator but on an iPhone SE it crashes after 50 seconds or short before a million images.
Is it a bug or is there another explanation since it doesn't crash in the simulator and I cannot see a memory leak in jvisualvm?
Here is the code:
public class FormMeasureImage extends Form implements Painter {
abstract class Wallpaper implements Painter {
private Component componentParent;
public Wallpaper(Component aComponentParent) {
componentParent = aComponentParent;
}
public void paint(Graphics aGraphics, Rectangle aRectangle) {
aGraphics.drawImage(
getImage(new Dimension(componentParent.getWidth(), componentParent.getHeight())),
0,
0);
}
public abstract Image getImage(Dimension aDimension);
}
class WallpaperTiledIcons extends Wallpaper {
private Image image;
private Dimension dimension;
public WallpaperTiledIcons(Component aComponentParent) {
super(aComponentParent);
}
public Image getImage(Dimension aDimension) {
if ((null == image || !dimension.equals(aDimension)) && null != aDimension) {
dimension = new Dimension(aDimension);
Label labelPattern = new Label("1234567890");
Style styleLabelPattern = labelPattern.getAllStyles();
styleLabelPattern.setBorder(Border.createEmpty());
styleLabelPattern.setMargin(0, 0, 0, 0);
// byte[] bytes = new byte[4];
// Arrays.fill(bytes, Style.UNIT_TYPE_PIXELS);
// styleLabelPattern.setPaddingUnit(bytes);
styleLabelPattern.setPadding(0, 0, 0, 1);
Dimension preferredSizeLabelPattern = labelPattern.getPreferredSize();
labelPattern.setSize(preferredSizeLabelPattern);
Image imagePattern = Image.createImage(
preferredSizeLabelPattern.getWidth(),
preferredSizeLabelPattern.getHeight(),
0x00000000);
Graphics graphicsImagePattern = imagePattern.getGraphics();
graphicsImagePattern.setAlpha(255);
labelPattern.paint(graphicsImagePattern);
image = Image.createImage(
aDimension.getWidth(),
aDimension.getHeight(),
0xff606060);
Graphics graphics = image.getGraphics();
if (graphics.isAntiAliasingSupported()) {
graphics.setAntiAliased(true);
}
int canvasWidth = preferredSizeLabelPattern.getWidth(), canvasHeight = preferredSizeLabelPattern.getHeight();
int[] clip = graphics.getClip();
Rectangle rectangleClip = new Rectangle(clip[0], clip[1], clip[2], clip[3]);
int columns = (rectangleClip.getX() + rectangleClip.getWidth()) / canvasWidth + 1;
int rows = (rectangleClip.getY() + rectangleClip.getHeight()) / canvasHeight + 1;
for (int row = 0; row < rows; row++) {
for (int column = 0; column < columns; column++) {
int x = canvasWidth * column;
int y = canvasHeight * row;
Rectangle rectangle = new Rectangle(x, y, canvasWidth, canvasHeight);
if (!rectangleClip.intersects(rectangle)) {
continue;
}
graphics.drawImage(imagePattern, x, y);
}
}
}
return image;
}
}
abstract class Stage {
long millisTotal;
long tally;
TextArea textArea;
public Stage(String aName) {
textArea = new TextArea();
textArea.setEditable(false);
getContentPane().add(textArea);
stages.add(this);
}
abstract void perform();
abstract boolean isPainted();
}
private Wallpaper wallpaper;
private List<Stage> stages = new ArrayList<>();
private Iterator<Stage> iteratorStages;
private Image imageEncoded;
public FormMeasureImage() {
super("FormMeasureImage", new BoxLayout(BoxLayout.Y_AXIS));
setScrollableX(false);
setScrollableY(true);
Style styleForm = getAllStyles();
styleForm.setBgTransparency(255);
styleForm.setBgPainter(this);
TextArea textArea = new TextArea();
textArea.setEditable(false);
textArea.setText("Measuring image throughput.");
add(textArea);
}
#Override
public void paint(Graphics aGraphics, Rectangle aRectangle) {
if (null == iteratorStages) {
new Stage("create") {
void perform() {
long millisBefore = System.currentTimeMillis();
wallpaper = new WallpaperTiledIcons(FormMeasureImage.this);
wallpaper.getImage(aRectangle.getSize());
millisTotal += System.currentTimeMillis() - millisBefore;
tally++;
textArea.setText("create: " + millisTotal + " / " + tally);
}
boolean isPainted() {
return false;
}
};
new Stage("mutable") {
void perform() {
long millisBefore = System.currentTimeMillis();
for (int index = 0; index < 1000; index++) {
wallpaper.paint(aGraphics, aRectangle);
tally++;
}
millisTotal += System.currentTimeMillis() - millisBefore;
textArea.setText("mutable: " + millisTotal + " / " + tally);
}
boolean isPainted() {
return true;
}
};
new Stage("encoding") {
void perform() {
long millisBefore = System.currentTimeMillis();
try {
millisBefore = System.currentTimeMillis();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ImageIO.getImageIO().save(wallpaper.getImage(null), byteArrayOutputStream, ImageIO.FORMAT_PNG, 1);
byteArrayOutputStream.close();
imageEncoded = Image.createImage(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
tally++;
millisTotal += System.currentTimeMillis() - millisBefore;
textArea.setText("encoding: " + millisTotal + " / " + tally);
} catch (IOException e) {
throw new RuntimeException(e.toString());
}
millisTotal += System.currentTimeMillis() - millisBefore;
tally++;
textArea.setText("encoding: " + millisTotal + " / " + tally);
}
boolean isPainted() {
return false;
}
};
new Stage("encoded") {
void perform() {
long millisBefore = System.currentTimeMillis();
for (int index = 0; index < 1000; index++) {
aGraphics.drawImage(
imageEncoded,
0,
0);
tally++;
}
millisTotal += System.currentTimeMillis() - millisBefore;
textArea.setText("encoded: " + millisTotal + " / " + tally);
}
boolean isPainted() {
return true;
}
};
iteratorStages = stages.iterator();
}
while (!perform().isPainted()) {;}
}
private Stage perform() {
if (!iteratorStages.hasNext()) {
iteratorStages = stages.iterator();
}
Stage stage = iteratorStages.next();
stage.perform();
return stage;
}
}
It seems that the test case included an EDT violation of decoding off the EDT. This can work for some cases but because of the heavy usage it crashes.
Making UI code threadsafe is a difficult task which is doubly so cross platforms.
I'm trying to store girl and boy names into an array.
I got most of the code except the storing the files into an array.
This is what girls.txt looks like
Emma 125125
Elaina 415545
Kim 545454
Boys.txt:
Devan 45645
Tom 4545
Chris 4879797
i need help storing the names and numbers from files into array boynames array and girlnames array. I show where i need help with comments in code
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Project1Names {
public static void main(String[] args) {
Scanner inputStream = null;
String[][] boynames = new String[1000][2];
String[][] girlnames = new String[1000][2];
String line = null;
boolean isFoundB = false;
boolean isFoundG = false;
try {
inputStream = new Scanner(new FileInputStream("boys.txt"));
} catch (FileNotFoundException e) {
System.out.println("Problem opening file boys.txt");
System.exit(0);
}
Scanner inputStreamGirls = null;
try {
inputStreamGirls = new Scanner(new FileInputStream("girls.txt"));
} catch (FileNotFoundException e) {
System.out.println("Problem opening file girls.txt");
System.exit(0);
}
int count = 0;
while (count < 1000){
inputStream = boynames[count][0]; //Error here
inputStream = boynames[count][1]; //here
count++;
}
count = 0;
while (count < 1000 ){
inputStreamGirls = girlnames[count][0]; //here
inputStreamGirls = girlnames[count][1]; //here
count++;
}
Scanner keyboard = new Scanner(System.in);
System.out.println("Enter the first name that you would like to find the popularity of.\n Be sure to capitalize the first letter of the name.\n");
String answer = keyboard.next();
count = 0;
while(count < 1000){
if (boynames[count][0] == answer){
System.out.println(boynames[count][0] + " is ranked " + count + " among boys with " + boynames[count][1] + " namings");
isFoundB = true;
}
if (girlnames[count][0] == answer){
System.out.println(girlnames[count][0] + " is ranked " + count + " among girls with " + girlnames[count][1] + " namings");
isFoundG = true;
}
count++;
}
if(isFoundB == false){
System.out.println(answer + " is not ranked among the top 1000 boy names.");
}
if(isFoundG == false){
System.out.println(answer + " is not ranked among the top 1000 girl names.");
}
inputStreamGirls.close();
inputStream.close();
keyboard.close();
}
}
You will need to call the scanner methods to actually read from the input file.
scanner.next() reads one string token from the input.
So instead of this part:
inputStream = boynames[count][0]; //Error here
inputStream = boynames[count][1]; //here
You would do:
boynames[count][0] = inputStream.next();
boynames[count][1] = inputStream.next();
I've made a simple text box which when a button is pressed loads the text from a text file (line by line). It writes the numbers to a JTextArea then it applies some methods to the numbers and outputs the results into a JTextArea.
My problem is that when the output is shown it repeats the lines - it is easier to show by example.
So if the text file reads:
1
2
The output given is:
First TextArea:
1
2
Second TextArea:
resultFrom1
resultFrom1
resultFrom2
So the numbers are displaying fine but the processed data is repeating itself. In this case it shows the program displaying the first result and then displaying both results.
The code for the load button is:
private void loadPlaylistBtnActionPerformed(java.awt.event.ActionEvent evt) {
if (evt.getSource() == loadPlaylistBtn) {
try {
playlistTextArea.setText(null);
FileReader fileReader = new FileReader("playlist.txt");
BufferedReader bufferedReader = new BufferedReader(fileReader);
String inputFile = "";
String textFieldReadable = bufferedReader.readLine();
while (textFieldReadable != null) {
inputFile += textFieldReadable + "\n";
textFieldReadable = bufferedReader.readLine();
trackNum.setText(inputFile);
String[] loadPlaylist = trackNum.getText().split("\\n");
for (int i = 0; i < loadPlaylist.length; ++i) {
String songName = LibraryData.getName(loadPlaylist[i]);
String songArtist = LibraryData.getArtist(loadPlaylist[i]);
playlistTextArea.append(songName + " - " + songArtist + "\n");
}
}
fileReader.close();
} catch (Exception e) {
System.out.println("File not found.");
}
}
}
The methods in LibraryData are:
getName:
public static String getName(String key) {
try {
stmt = con.createStatement();
ResultSet res = stmt.executeQuery("SELECT * FROM Library WHERE LibraryID = '" +
key + "'");
if (res.next()) {
return res.getString(2);
} else {
return null;
}
} catch (Exception e) {
return null;
}
}
and getArtist:
public static String getArtist(String key) {
try {
stmt = con.createStatement();
ResultSet res = stmt.executeQuery("SELECT * FROM Library WHERE LibraryID = '" + key + "'");
if (res.next()) {
return res.getString(3);
} else {
return null;
}
} catch (Exception e) {
return null;
}
}
Any ideas on how I can make it just output one of the songs relating to the number, rather than repeating itself?
Sorry if this has been really unclear - I'm still quite new to Java.
Thanks :)
Using the assumption that playlistTextArea is your problem test box, the problem seems to be:
playlistTextArea.append(songName + " - " + songArtist + "\n");
You're reading the file lines one at a time, and then appending the entire list every single time, which will result in the pattern 1, 1, 2, 1, 2, 3, 1, 2, 3, 4, etc. Easiest way to resolve this would be to make sure you clear the text box before the for loop (i.e. - Move to the playlistTextArea.setText(null) down).
I am developing silverlight web part by using the client object model. I am getting the bitmap image from sharepoint server. Now I want to save this bitmap image in isolated storage. So I am using following code
WriteableBitmap wb = new WriteableBitmap(attachments);
using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream isoStream =
new IsolatedStorageFileStream("abcd1.jpg", FileMode.Create, isoFile))
{
using (StreamWriter sw = new StreamWriter(isoStream))
{
sw.Write(wb.ToByteArray());
}
}
}
Now I am seeing the saved image at location C:\Users\Rent2\AppData\LocalLow\Microsoft\Silverlight\is\vzvpufsm.s4i\m0laonzr.til\1\s\nkhajster01es5wdoyfxd0n5rd2dls3ovyu4wcdig04zjx44hyaaafea\f
When I click on it, it gives me message as "Invalid Image". Can you please tell me how should i write code so that I can see the actual image after saving it in isolated storage ?
private void zipFile()
{
context = Microsoft.SharePoint.Client.ClientContext.Current;
Microsoft.SharePoint.Client.File.OpenBinaryDirect(
context,
#"/TemplateInvoice/" + App.templateFileName + ".xlsx", successFile, FailFile);
}
private void successFile(object sender, OpenBinarySucceededEventArgs args)
{
System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() =>
{
// Obtain the isolated storage for an application.
try
{
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
Stream strm = args.Stream;
using (var isoStream = store.OpenFile(App.templateFileName + ".zip", FileMode.OpenOrCreate))
{
// Read the resource file into a byte array.
bytes = new byte[strm.Length];
int numBytesToRead = (int)strm.Length;
int numBytesRead = 0;
while (numBytesToRead > 0)
{
// Read may return anything from 0 to numBytesToRead.
int n = strm.Read(bytes, numBytesRead, numBytesToRead);
// The end of the file is reached.
if (n == 0)
break;
numBytesRead += n;
numBytesToRead -= n;
}
numBytesToRead = bytes.Length;
// Write the byte array to the IsolatedStorageFileStream.
isoStream.Write(bytes, 0, numBytesToRead);
//isoStream.Dispose();
}
strm.Close();
string path = App.templateFileName + ".zip";
ZipHelp.UnZip(path, System.IO.Path.GetDirectoryName(path), 4096);
replaceFileContent();
string rootDirectory = System.Windows.Browser.HttpUtility.UrlDecode(path);
string fileName = ZipHelp.Zip(rootDirectory.Replace(".zip", ""), invoice);
//string filename = DateTime.Now.Day.ToString() + DateTime.Now.Month.ToString() + DateTime.Now.Year.ToString() + DateTime.Now.Hour.ToString() + DateTime.Now.Minute.ToString() + DateTime.Now.Second.ToString() + "Invoice1.xlsx";
// Read the resource file into a byte array.
using (var stream = store.OpenFile(fileName, FileMode.Open))
{
bytes = new byte[stream.Length];
int numBytesToRead = (int)stream.Length;
int numBytesRead = 0;
while (numBytesToRead > 0)
{
// Read may return anything from 0 to numBytesToRead.
int n = stream.Read(bytes, numBytesRead, numBytesToRead);
// The end of the file is reached.
if (n == 0)
break;
numBytesRead += n;
numBytesToRead -= n;
}
InvoiceTemplete invoiceTemplate = new InvoiceTemplete(fileName, bytes, SetMessage);
invoiceTemplate.AddDocument(invoiceTemplate);
}
}
//mark rows as billed
foreach (var item in PrivatePayList)
{
MedwaiverViewModel MedwaiverViewModelObj = new MedwaiverViewModel();
MedwaiverViewModelObj.ChangeBillingStatus(item.ListItemId, "Billed");
if (MedwaiverTimeLogList != null)
{
MedwaiverTimeLogList.Remove(item);
}
if (ClientSpecificTimeLogList != null)
{
ClientSpecificTimeLogList.Remove(item);
}
if (rangeBoundTimeLogListForDate != null)
{
rangeBoundTimeLogListForDate.Remove(item);
}
if (vRangeBoundTimeLogListForDateAndClient != null)
{
vRangeBoundTimeLogListForDateAndClient.Remove(item);
}
}
}
catch (IsolatedStorageException isx)
{
MessageBox.Show(isx.Message);
}
});
}
private void FailFile(object sender, OpenBinaryFailedEventArgs e)
{
System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() =>
{
MessageBox.Show("Fail");
});
}
//The following class zip and unzip the file
class ZipHelp
{
static List<string> folderPathList = new List<string>();
public static string Zip(string rootDirectory, string fileName)
{
byte[] buffer;
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
IsolatedStorageFileStream zipFileStream = store.CreateFile(fileName + ".xlsx");
ZipOutputStream zipOutStream = new ZipOutputStream(zipFileStream);
zipOutStream.UseZip64 = UseZip64.Off;
//zipOutStream.CanPatchEntries
foreach (var item in folderPathList)
{
string entryName = "";
buffer = new byte[4096];
if (item.Substring(0,1) == #"/")
{
//removes leading /
entryName = item.Substring(1);
}
else
{
entryName = item;
}
ZipEntry entry = new ZipEntry(entryName);
//entry.CompressionMethod = CompressionMethod.Deflated;
//entry.
entry.IsZip64Forced();
//entry.IsDirectory
zipOutStream.PutNextEntry(entry);
using (IsolatedStorageFileStream stream = store.OpenFile(rootDirectory + #"\" + item, FileMode.Open))
{
int size;
do
{
size = stream.Read(buffer, 0, buffer.Length);
zipOutStream.Write(buffer, 0, size);
} while (size > 0);
stream.Close();
}
}
zipOutStream.Close();
zipFileStream.Close();
}
return fileName + ".xlsx";
//string[] directories = GetLocationTypes();
//zip();
//string[] filenames = Directory.GetFiles(directories);
//using (var store = IsolatedStorageFile.GetUserStoreForApplication())
//{
// using (var isoStream = store.OpenFile("#" + rootDirectory, FileMode.OpenOrCreate))
// {
// //foreach(string dir in
// }
//}
}
private static string[] GetLocationTypes()
{
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
return store.GetDirectoryNames();
}
}
/// <summary>
/// UnZip a file
/// </summary>
/// <param name="SrcFile">source file path</param>
/// <param name="DstFile">unzipped file path</param>
/// <param name="BufferSize">buffer to use</param>
public static void UnZip(string SrcFile, string DstFile, int BufferSize)
{
folderPathList.Clear();
IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication();
FileStream fileStreamIn = store.OpenFile(SrcFile, FileMode.Open, FileAccess.Read);
ZipInputStream zipInStream = new ZipInputStream(fileStreamIn);
string rootDirectory = System.Windows.Browser.HttpUtility.UrlDecode(SrcFile);
rootDirectory = rootDirectory.Replace(".zip", "");
store.CreateDirectory(rootDirectory);
while (true)
{
ZipEntry entry = zipInStream.GetNextEntry();
if (entry == null)
break;
if (entry.Name.Contains("/"))
{
string[] folders = entry.Name.Split('/');
string lastElement = folders[folders.Length - 1];
var folderList = new List<string>(folders);
folderList.RemoveAt(folders.Length - 1);
folders = folderList.ToArray();
string folderPath = "";
foreach (string str in folders)
{
folderPath = folderPath + "/" + str;
if (!store.DirectoryExists(rootDirectory + "/" + folderPath))
{
store.CreateDirectory(rootDirectory + "/" + folderPath);
}
}
folderPath = folderPath + "/" + lastElement;
writeToFile(BufferSize, fileStreamIn, zipInStream, rootDirectory, folderPath);
}
else
{
writeToFile(BufferSize, fileStreamIn, zipInStream, rootDirectory, entry.Name);
}
}
zipInStream.Close();
fileStreamIn.Close();
}
private static void writeToFile(int BufferSize, FileStream fileStreamIn, ZipInputStream zipInStream, string rootDirectory, string folderPath)
{
IsolatedStorageFile store1 = IsolatedStorageFile.GetUserStoreForApplication();
FileStream fileStreamOut = store1.OpenFile(rootDirectory + "/" + folderPath, FileMode.Create, FileAccess.Write);
folderPathList.Add(folderPath);
int size;
byte[] buffer = new byte[BufferSize];
do
{
size = zipInStream.Read(buffer, 0, buffer.Length);
fileStreamOut.Write(buffer, 0, size);
} while (size > 0);
fileStreamOut.Close();
}
}
I can think of two viable options here.
In your code above, save off the Pixels array of the WriteableBitmap. Then to restore it, you would create a WriteableBitmap of the appropriate size and the set the Pixels array to the stored data.
-or-
Use a HttpWebRequest or WebClient request to get the raw image stream and save that to IsolatedStorage.
There are pros and cons to each of these, in the first case the data is uncompressed and will take up more space in isolated storage and you would not be able to open the image from disk outside of Silverlight, similar to the issue you had above. For the second option you can run into cross domain issues if the images are on a different server than your Silverlight XAP file and it's also a bit more complex to implement.
The basic problem is that you're storing the decoded RGBA pixels array as a JPEG file - but they're not the same. Your code is basically correct: you just can't use this method to store it as a JPEG file. But if you happen to know that the image is, say, 800x600, you could create an 800x600 WriteableBitmap, and then set the Pixels property to the retrieved stream's byte array. Or if you don't know the dimensions when you're retrieving it, you could store the dimensions as the first two integers in the stream (before you write the pixels to the stream), and read out the dimensions when you're reading the file. You'd effectively be creating your own very simplistic .bmp format.