downloadUrlToStorageInBackground in ImageList model for imageViewer downloads & overrides the image every time - codenameone

class ImageList implements ListModel<Image> {
private int selection;
private Image[] images;
private EventDispatcher listeners = new EventDispatcher();
public ImageList() {
this.images = new EncodedImage[imageURLs.length];
}
public Image getItemAt(final int index) {
if (images[index] == null) {
images[index] = placeholderForTable;
Util.downloadUrlToStorageInBackground(imageURLs[index], "list" + index, (e) -> {
try {
images[index] = EncodedImage.create(Storage.getInstance().createInputStream("list" + index));
listeners.fireDataChangeEvent(index, DataChangedListener.CHANGED);
} catch (IOException err) {
err.printStackTrace();
}
});
}
return images[index];
}
public int getSize() {
return imageURLs.length;
}
public int getSelectedIndex() {
return selection;
}
public void setSelectedIndex(int index) {
selection = index;
}
public void addDataChangedListener(DataChangedListener l) {
listeners.addListener(l);
}
public void removeDataChangedListener(DataChangedListener l) {
listeners.removeListener(l);
}
public void addSelectionListener(SelectionListener l) {
}
public void removeSelectionListener(SelectionListener l) {
}
public void addItem(Image item) {
}
public void removeItem(int index) {
}
}
protected void postMenuForm(Form f) {
BusinessForumImagesConnection bfic = new BusinessForumImagesConnection();
bfic.businessForumImagesConnectionMethod(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
if (bfic.response != null) {
for (int i = 0; i < imgLoop; i++) {
HashMap hm = (HashMap) bfic.response.get(i);
String imgUrl = (String) hm.get("imgUrl");
imageURLs[i] = imgUrl;
}
}
}
});
if (imageURLs != null) {
ImageList imodel = new ImageList();
ImageViewer iv = new ImageViewer(imodel.getItemAt(0));
iv.setImageList(imodel);
Container adsContainer = BoxLayout.encloseY(adsLabel, iv);
slideIndex = 0;
Runnable r = new Runnable() {
public void run() {
if (slideIndex < imodel.getSize()) {
nextImage = (Image) imodel.getItemAt(slideIndex);
if (nextImage != null) {
iv.setImage(nextImage);
}
slideIndex++;
} else {
slideIndex = 0;
}
}
};
if (uITimer == null) {
uITimer = new UITimer(r);
}
if (uITimer != null) {
uITimer.schedule(5000, true, f); //5 seconds
}
f.add(BorderLayout.SOUTH, adsContainer);
adsContainer.setLeadComponent(adsLabel);
adsLabel.addActionListener((e) -> {
showForm("BusinessForum", null);
});
}
}
I had used URLImage.createToStorage before but imageViewer didnt work properly so I have used ImageList model. But everytime the form is opened, it jst redownloads the imgs and overrides them in storage, that makes the app slower. How can I make sure if the image is already downloaded, it doesnt download it again and jst shows them in imgViewer? thankyou

The download method will always download regardless...
You need to check if the Storage file exists and if so load that.
See the WebServices/Dogs demo in the new kitchen sink: http://www.codenameone.com/blog/kitchensink-ii.html

Related

Combining two instantiate scripts (Unity 3D)

I need to combine the following scripts into one script containing two functions, one that instantiates the next prefab in the array and the other that instantiates the previous prefab in the array (it is a virtual tour app). Both should also destroy the current prefab. I could then call the functions via event triggers.
I have this code for the "next Prefab" script.
public GameObject[] Spheres;
int currentIndex = 0;
GameObject currentObject;
public Camera MainCamera;
void OnMouseDown()
{
if (Input.GetMouseButtonDown(0))
if (gameObject.tag == "ArrowNEXT")
{
Vector3 rayOrigin = MainCamera.ViewportToWorldPoint(new Vector3(0.1f, 0.1f, 0));
RaycastHit hit;
if (Physics.Raycast(rayOrigin, MainCamera.transform.forward, out hit))
{
if (hit.collider != null)
{
{
Destroy(currentObject);
currentIndex++;
if (currentIndex > Spheres.Length - 1) currentIndex = 0;
currentObject = Instantiate(Spheres[currentIndex]);
}
}
}
}
}
I need to combine it with the following:
using UnityEngine;
public class RayCastPrevFIX: MonoBehaviour
{
public GameObject[] Spheres;
int currentIndex = 0;
GameObject currentObject;
public Camera MainCamera;
void OnMouseDown()
{
if (Input.GetMouseButtonDown(0))
if (gameObject.tag == "ArrowPREV")
{
Vector3 rayOrigin = MainCamera.ViewportToWorldPoint(new Vector3(0.1f, 0.1f, 0));
RaycastHit hit;
if (Physics.Raycast(rayOrigin, MainCamera.transform.forward, out hit))
{
if (hit.collider != null)
{
{
Destroy(currentObject);
currentIndex--;
if (currentIndex < 0) currentIndex = Spheres.Length - 1;
currentObject = Instantiate(Spheres[currentIndex]);
}
}
}
}
}
}
How would I go about this? Any help is greatly appreciated.I have this so far:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SphereSwap : MonoBehaviour
{
public GameObject[] Spheres;
int currentIndex = 0;
GameObject currentObject;
public Camera MainCamera;
void Next()
{
Destroy(currentObject);
currentIndex++;
if (currentIndex > Spheres.Length - 1) currentIndex = 0;
currentObject = Instantiate(Spheres[currentIndex]);
}
void Previous()
{
Destroy(currentObject);
currentIndex--;
if (currentIndex < 0) currentIndex = Spheres.Length - 1;
currentObject = Instantiate(Spheres[currentIndex]);
}
}
You're on the right path, but you could shorten the code as well as use one function for both cases to avoid boilerplate:
using UnityEngine;
public class SphereSwap : MonoBehaviour
{
public GameObject[] Spheres;
int currentIndex = 0;
GameObject currentObject;
public Camera MainCamera;
const string ArrowPrevTag = "ArrowPREV";
const string ArrowNextTag = "ArrowNEXT";
private void HandleClick(bool next)
{
if(Spheres == null || Spheres.Length == 0)
{
Debug.Log($"Spheres list is empty, nothing to swap.");
return;
}
Vector3 rayOrigin = MainCamera.ViewportToWorldPoint(new Vector3(0.1f, 0.1f, 0));
RaycastHit hit;
if (Physics.Raycast(rayOrigin, MainCamera.transform.forward, out hit))
{
if (hit.collider != null)
{
// destroy current sphere.
Destroy(currentObject);
// go next or previous.
currentIndex += next ? 1 : -1;
// circular clamp if overflow
if (currentIndex < 0)
currentIndex = Spheres.Length - 1;
else if (currentIndex >= Spheres.Length)
currentIndex = 0;
// finally do instantiate.
currentObject = Instantiate(Spheres[currentIndex]);
}
}
}
private void OnMouseDown()
{
if (Input.GetMouseButtonDown(0))
{
// 'CompareTag' is more efficient than gameobject.tag == "sometag"
if (gameObject.CompareTag(ArrowNextTag))
HandleClick(true);
else if (gameObject.CompareTag(ArrowPrevTag))
HandleClick(false);
}
}
}

Is there any way to pass Observable<String> into AbstractInputStreamContent?

I'm working on uploading a text file to Google Drive
ByteArrayContent content = new ByteArrayContent("text/csv", fileContent.getBytes(Charset.forName("UTF-8")));
Drive.Files.Insert request = drive.files().insert(file, content);
where type(fileContent) = String
I'd like to refactor and change type of fileContent to Observable<String>, is there any nice workaround to pass it to that insert() function (which takes AbstractInputStreamContent as a second argument)?
Thanks
Here is a general Flowable -> InputStream bridge you can delegate to:
import java.io.*;
import java.nio.charset.Charset;
import java.util.concurrent.atomic.AtomicReference;
import org.reactivestreams.*;
import io.reactivex.FlowableSubscriber;
import io.reactivex.internal.subscriptions.SubscriptionHelper;
public final class FlowableStringInputStream {
private FlowableStringInputStream() {
throw new IllegalStateException("No instances!");
}
public static InputStream createInputStream(
Publisher<String> source, Charset charset) {
StringInputStream parent = new StringInputStream(charset);
source.subscribe(parent);
return parent;
}
static final class StringInputStream extends InputStream
implements FlowableSubscriber<String> {
final AtomicReference<Subscription> upstream;
final Charset charset;
volatile byte[] bytes;
int index;
volatile boolean done;
Throwable error;
StringInputStream(Charset charset) {
this.charset = charset;
upstream = new AtomicReference<>();
}
#Override
public void onSubscribe(Subscription s) {
if (SubscriptionHelper.setOnce(upstream, s)) {
s.request(1);
}
}
#Override
public void onNext(String t) {
bytes = t.getBytes(charset);
synchronized (this) {
notifyAll();
}
}
#Override
public void onError(Throwable t) {
error = t;
done = true;
synchronized (this) {
notifyAll();
}
}
#Override
public void onComplete() {
done = true;
synchronized (this) {
notifyAll();
}
}
#Override
public int read() throws IOException {
for (;;) {
byte[] a = awaitBufferIfNecessary();
if (a == null) {
Throwable ex = error;
if (ex != null) {
if (ex instanceof IOException) {
throw (IOException)ex;
}
throw new IOException(ex);
}
return -1;
}
int idx = index;
if (idx == a.length) {
index = 0;
bytes = null;
upstream.get().request(1);
} else {
int result = a[idx] & 0xFF;
index = idx + 1;
return result;
}
}
}
byte[] awaitBufferIfNecessary() throws IOException {
byte[] a = bytes;
if (a == null) {
synchronized (this) {
for (;;) {
boolean d = done;
a = bytes;
if (a != null) {
break;
}
if (d || upstream.get() == SubscriptionHelper.CANCELLED) {
break;
}
try {
wait();
} catch (InterruptedException ex) {
if (upstream.get() != SubscriptionHelper.CANCELLED) {
InterruptedIOException exc = new InterruptedIOException();
exc.initCause(ex);
throw exc;
}
break;
}
}
}
}
return a;
}
#Override
public int read(byte[] b, int off, int len) throws IOException {
if (off < 0 || len < 0 || off >= b.length || off + len > b.length) {
throw new IndexOutOfBoundsException(
"b.length=" + b.length + ", off=" + off + ", len=" + len);
}
for (;;) {
byte[] a = awaitBufferIfNecessary();
if (a == null) {
Throwable ex = error;
if (ex != null) {
if (ex instanceof IOException) {
throw (IOException)ex;
}
throw new IOException(ex);
}
return -1;
}
int idx = index;
if (idx == a.length) {
index = 0;
bytes = null;
upstream.get().request(1);
} else {
int r = 0;
while (idx < a.length && len > 0) {
b[off] = a[idx];
idx++;
off++;
r++;
len--;
}
index = idx;
return r;
}
}
}
#Override
public int available() throws IOException {
byte[] a = bytes;
int idx = index;
return a != null ? Math.max(0, a.length - idx) : 0;
}
#Override
public void close() throws IOException {
SubscriptionHelper.cancel(upstream);
synchronized (this) {
notifyAll();
}
}
}
}
Usage:
#Test(timeout = 10000)
public void async() throws Exception {
AtomicInteger calls = new AtomicInteger();
Flowable<String> f = Flowable.range(100, 10).map(Object::toString)
.doOnCancel(() -> calls.incrementAndGet())
.subscribeOn(Schedulers.computation())
.delay(10, TimeUnit.MILLISECONDS);
try (InputStream is = FlowableStringInputStream.createInputStream(f, utf8)) {
assertEquals('1', is.read());
assertEquals('0', is.read());
assertEquals('0', is.read());
byte[] buf = new byte[3];
assertEquals(3, is.read(buf));
assertArrayEquals("101".getBytes(utf8), buf);
}
assertEquals(1, calls.get());
}

How to build a swipable intro screen?

A lot of apps have swipable intro screens - You know - those with the dots below which indicate the page one is currently viewing.
What would be the best way to create one in Codename One - a Container with snapToGrid?
I have my own implementation for this use case. There are two classes : TutoDialog which could be in your case the "intro screens" dialog and Caroussel with the dots indicator.
A tuto dialog has a title and some images in parameter. It automatically adjust the number of dots of the caroussel according to the number of images. For my use case, each image is a screenshot of my app with some advise. The tuto dialog contains 3 buttons to navigate between images (next/previous/finish).
public class Caroussel extends Container {
private final static Image CIRCLE = MainClass.getResources().getImage("circle-blue20.png");
private final static Image CIRCLE_EMPTY = MainClass.getResources().getImage("circle-empty-blue20.png");
private Label[] circles;
private int currentIndex = -1;
public Caroussel(int nbItems, boolean selectFirst) {
if (nbItems < 2 || nbItems > 50) {
throw new IllegalArgumentException("Can't create Caroussel component with nbItems<2 || nbItems>50 ! ");
}
this.circles = new Label[nbItems];
setLayout(new BoxLayout(BoxLayout.X_AXIS));
for (int i = 0; i < nbItems; i++) {
circles[i] = new Label("", CIRCLE_EMPTY);
add(circles[i]);
}
if (selectFirst) {
select(0);
}
}
public void select(int index) {
if (index >= 0 && index <= circles.length) {
if (currentIndex > -1) {
circles[currentIndex].setIcon(CIRCLE_EMPTY);
}
circles[index].setIcon(CIRCLE);
currentIndex = index;
repaint();
}
}
public void selectNext() {
if (currentIndex <= circles.length) {
select(currentIndex + 1);
}
}
public void selectPrevious() {
if (currentIndex >= 1) {
select(currentIndex - 1);
}
}}
And
public class TutoDialog extends Dialog {
private Caroussel caroussel = null;
public TutoDialog(String title, Image... images) {
if (images == null) {
return;
}
this.caroussel = new Caroussel(images.length, true);
setTitle(title);
setAutoAdjustDialogSize(true);
getTitleComponent().setUIID("DialogTitle2");
setBlurBackgroundRadius(8.5f);
Tabs tabs = new Tabs();
tabs.setSwipeActivated(false);
tabs.setAnimateTabSelection(false);
int px1 = DisplayUtil.getScaledPixel(800), px2 = DisplayUtil.getScaledPixel(600);
for (Image img : images) {
tabs.addTab("", new Label("", img.scaled(px1, px2)));
}
Container cButtons = new Container(new BorderLayout());
Button bSuivant = new Button("button.suivant");
Button bPrecedent = new Button("button.precedent");
Button bTerminer = new Button("button.terminer");
bPrecedent.setVisible(false);
bTerminer.setVisible(false);
bSuivant.addActionListener(new ActionListener<ActionEvent>() {
public void actionPerformed(ActionEvent evt) {
int currentInd = tabs.getSelectedIndex();
if (currentInd == 0) {
bPrecedent.setVisible(true);
}
if (currentInd + 1 <= tabs.getTabCount() - 1) {
if (caroussel != null)
caroussel.selectNext();
tabs.setSelectedIndex(currentInd + 1);
if (currentInd + 1 == tabs.getTabCount() - 1) {
bTerminer.setVisible(true);
bSuivant.setVisible(false);
cButtons.revalidate();
}
}
};
});
bPrecedent.addActionListener(new ActionListener<ActionEvent>() {
public void actionPerformed(ActionEvent evt) {
int currentInd = tabs.getSelectedIndex();
tabs.setSelectedIndex(currentInd - 1);
bSuivant.setVisible(true);
if (caroussel != null)
caroussel.selectPrevious();
if (currentInd - 1 == 0) {
bPrecedent.setVisible(false);
cButtons.revalidate();
}
};
});
bTerminer.addActionListener(new ActionListener<ActionEvent>() {
#Override
public void actionPerformed(ActionEvent evt) {
tabs.setSelectedIndex(0);
bPrecedent.setVisible(false);
bTerminer.setVisible(false);
bSuivant.setVisible(true);
if (caroussel != null)
caroussel.select(0);
TutoDialog.this.dispose();
}
});
cButtons.add(BorderLayout.WEST, bPrecedent).add(BorderLayout.CENTER, bSuivant).add(BorderLayout.EAST, bTerminer);
add(BoxLayout.encloseY(tabs, BoxLayout.encloseY(FlowLayout.encloseCenter(caroussel), cButtons)));
}
public static void showIfFirstTime(AbstractComponentController ctrl) {
if (ctrl == null) {
Log.p("Can't execute method showIfFirstTime(...) with null AbstractComponentController");
return;
}
String key = getKey(ctrl);
if (ctrl.getTutoDlg() != null && !Preferences.get(key, false)) {
Display.getInstance().callSerially(new Runnable() {
#Override
public void run() {
Preferences.set(key, true);
ctrl.getTutoDlg().show();
}
});
}
}
public static String getKey(AbstractComponentController ctrl) {
String key = "tuto" + ctrl.getClass().getSimpleName();
if (UserController.getCurrentUser() != null) {
key += "-" + UserController.getCurrentUser().getId();
}
return key;
}
public static boolean isAlreadyShown(AbstractComponentController ctrl) {
return Preferences.get(getKey(ctrl), false);
}
}
It's look like this :
OK - so that is my first attempt and I am pretty content with that:
private void showIntro() {
Display display = Display.getInstance();
int percentage = 60;
int snapWidth = display.getDisplayWidth() * percentage / 100;
int snapHeight = display.getDisplayHeight() * percentage / 100;
Dialog dialog = new Dialog(new LayeredLayout()) {
#Override
protected Dimension calcPreferredSize() {
return new Dimension(snapWidth, snapHeight);
}
};
Tabs tabs = new Tabs();
tabs.setTensileLength(0);
tabs.hideTabs();
int[] colors = {
0xc00000,
0x00c000,
0x0000c0,
0x909000,
0x009090,
};
for (int colorIndex = 0; colorIndex < colors.length; colorIndex++) {
Container containerElement = new Container() {
#Override
protected Dimension calcPreferredSize() {
return new Dimension(snapWidth, snapHeight);
}
};
Style style = containerElement.getAllStyles();
style.setBgTransparency(0xff);
style.setBgColor(colors[colorIndex]);
tabs.addTab("tab" + tabs.getTabCount(), containerElement);
}
int tabCount = tabs.getTabCount();
Button[] buttons = new Button[tabCount];
Style styleButton = UIManager.getInstance().getComponentStyle("Button");
styleButton.setFgColor(0xffffff);
Image imageDot = FontImage.createMaterial(FontImage.MATERIAL_LENS, styleButton);
for (int tabIndex = 0; tabIndex < tabCount; tabIndex++) {
buttons[tabIndex] = new Button(imageDot);
buttons[tabIndex].setUIID("Container");
final int tabIndexFinal = tabIndex;
buttons[tabIndex].addActionListener(aActionEvent -> tabs.setSelectedIndex(tabIndexFinal, true));
}
Container containerButtons = FlowLayout.encloseCenter(buttons);
dialog.add(tabs);
Button buttonWest = new Button("Skip");
buttonWest.setUIID("Container");
buttonWest.getAllStyles().setFgColor(0xffffff);
buttonWest.addActionListener(aActionEvent -> dialog.dispose());
Button buttonEast = new Button(">");
buttonEast.setUIID("Container");
buttonEast.getAllStyles().setFgColor(0xffffff);
buttonEast.addActionListener(aActionEvent -> {
int selectedIndex = tabs.getSelectedIndex();
if (selectedIndex < (tabs.getTabCount() - 1)) {
tabs.setSelectedIndex(selectedIndex + 1, true);
} else {
dialog.dispose();
}
});
Container containerSouth = BorderLayout.south(BorderLayout.centerAbsoluteEastWest(containerButtons, buttonEast, buttonWest));
Style styleContainerSouth = containerSouth.getAllStyles();
styleContainerSouth.setMarginUnit(
Style.UNIT_TYPE_DIPS,
Style.UNIT_TYPE_DIPS,
Style.UNIT_TYPE_DIPS,
Style.UNIT_TYPE_DIPS);
styleContainerSouth.setMargin(2, 2, 2, 2);
dialog.add(containerSouth);
SelectionListener selectionListener = (aOldSelectionIndex, aNewSelectionIndex) -> {
for (int buttonIndex = 0; buttonIndex < buttons.length; buttonIndex++) {
if (buttonIndex == aNewSelectionIndex) {
buttons[buttonIndex].getAllStyles().setOpacity(0xff);
} else {
buttons[buttonIndex].getAllStyles().setOpacity(0xc0);
}
}
buttonEast.setText((aNewSelectionIndex < (tabs.getTabCount() - 1)) ? ">" : "Finish");
buttonEast.getParent().animateLayout(400);
};
tabs.addSelectionListener(selectionListener);
dialog.addShowListener(evt -> {
buttonEast.getParent().layoutContainer();
selectionListener.selectionChanged(-1, 0);
});
Command command = dialog.showPacked(BorderLayout.CENTER, true);
}

Image Viewer auto slide codenamone

How can i auto slide the imageViewer for instance in the interval of 3 seconds.
Or is there any other component that can do the auto swipe task.
ImageViewer imv = new ImageViewer();
DefaultListModel<Image> images = new DefaultListModel<Image>(new Image[]{a, thumbnail1, thumbnail2});
imv.setImage(images.getItemAt(0));
imv.setImageList(images);
imv.setSwipePlaceholder(Image.createImage(100, 100));
Declare this global static variable:
private static int slideIndex = 0;
//And this UITimer
UITimer t;
And then try out below code
final ImageViewer imv = new ImageViewer();
final DefaultListModel<Image> images = new DefaultListModel<Image>(new Image[]{a, thumbnail1, thumbnail2});
imv.setImage(images.getItemAt(0));
imv.setImageList(images);
imv.setSwipePlaceholder(Image.createImage(100, 100));
Runnable r = new Runnable() {
public void run() {
if (slideIndex < images.getSize()) {
slideIndex++;
} else {
slideIndex = 0;
}
Image nextImage = (Image) images.getItemAt(slideIndex);
if (nextImage != null) {
imv.setImage(nextImage);
}
}
};
if (t == null) {
t = new UITimer(r);
}
if (t != null) {
t.schedule(3000, true, f); //3 seconds
}

LZH in Byte Array Decompress in .NET?

An LZH archive is embedded within a file. The file was read into a byte[], and the LZH part is identified as a smaller byte[].
How can the embedded LZH bytes be decompressed into another byte[] using .NET Framework 4.6 (C#)? I have only see http://www.infoq.com/news/2008/06/7-Zip-from-.NET which doesn't exactly do what I need.
Thanks.
the code snippet that follows is taken from the sample program from this article
http://www.codeproject.com/Articles/27148/C-NET-Interface-for-Zip-Archive-DLLs
There are no significant changes: instead of reading and writing files, it reads and write byte arrays. Changes are marked by comments
Run with sevenzip.exe e "C:\temp\gwo0.11-sample-win32.lzh" 3 for example
https://dl.dropboxusercontent.com/u/71459360/7z.zip
using System;
using System.Collections.Generic;
using System.Text;
using Nomad.Archive.SevenZip;
using System.IO;
using System.Runtime.InteropServices;
using System.Reflection;
namespace SevenZip
{
class Program
{
private static void ShowHelp()
{
Console.WriteLine("SevenZip");
Console.WriteLine("SevenZip l {ArchiveName}");
Console.WriteLine("SevenZip e {ArchiveName} {FileNumber}");
}
static void Main(string[] args)
{
if (args.Length < 2)
{
ShowHelp();
return;
}
try
{
string ArchiveName;
uint FileNumber = 0xFFFFFFFF;
bool Extract;
switch (args[0])
{
case "l":
ArchiveName = args[1];
Extract = false;
break;
case "e":
ArchiveName = args[1];
Extract = true;
if ((args.Length < 3) || !uint.TryParse(args[2], out FileNumber))
{
ShowHelp();
return;
}
break;
default:
ShowHelp();
return;
}
using (SevenZipFormat Format = new SevenZipFormat(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "7z.dll")))
{
IInArchive Archive = Format.CreateInArchive(SevenZipFormat.GetClassIdFromKnownFormat(KnownSevenZipFormat.Lzh));
if (Archive == null)
{
ShowHelp();
return;
}
try
{
//the byte array is provided by you. here it's coming from a file
byte[] data;
using (var stream = File.OpenRead(ArchiveName))
{
data = new byte[stream.Length];
stream.Read(data, 0, data.Length);
}
using (InStreamWrapper ArchiveStream = new InStreamWrapper(new MemoryStream(data))) //modified here
{
ulong CheckPos = 32 * 1024;
if (Archive.Open(ArchiveStream, ref CheckPos, null) != 0)
ShowHelp();
Console.Write("Archive: ");
Console.WriteLine(ArchiveName);
if (Extract)
{
PropVariant Name = new PropVariant();
Archive.GetProperty(FileNumber, ItemPropId.kpidPath, ref Name);
string FileName = (string) Name.GetObject();
Console.Write("Extracting: ");
Console.Write(FileName);
Console.Write(' ');
MemoryStream ms = new MemoryStream();
Archive.Extract(new uint[] { FileNumber }, 1, 0, new ArchiveMemoryCallback(FileNumber, ms)); //modified here
byte[] output = ms.ToArray(); //here you have the output byte array
output.ToString();
}
else
{
Console.WriteLine("List:");
uint Count = Archive.GetNumberOfItems();
for (uint I = 0; I < Count; I++)
{
PropVariant Name = new PropVariant();
Archive.GetProperty(I, ItemPropId.kpidPath, ref Name);
Console.Write(I);
Console.Write(' ');
Console.WriteLine(Name.GetObject());
}
}
}
}
finally
{
Marshal.ReleaseComObject(Archive);
}
}
}
catch (Exception e)
{
Console.Write("Error: ");
Console.WriteLine(e.Message);
}
}
}
class ArchiveCallback : IArchiveExtractCallback
{
private uint FileNumber;
private string FileName;
private OutStreamWrapper FileStream;
public ArchiveCallback(uint fileNumber, string fileName)
{
this.FileNumber = fileNumber;
this.FileName = fileName;
}
#region IArchiveExtractCallback Members
public void SetTotal(ulong total)
{
}
public void SetCompleted(ref ulong completeValue)
{
}
public int GetStream(uint index, out ISequentialOutStream outStream, AskMode askExtractMode)
{
if ((index == FileNumber) && (askExtractMode == AskMode.kExtract))
{
string FileDir = Path.GetDirectoryName(FileName);
if (!string.IsNullOrEmpty(FileDir))
Directory.CreateDirectory(FileDir);
FileStream = new OutStreamWrapper(File.Create(FileName));
outStream = FileStream;
}
else
outStream = null;
return 0;
}
public void PrepareOperation(AskMode askExtractMode)
{
}
public void SetOperationResult(OperationResult resultEOperationResult)
{
FileStream.Dispose();
Console.WriteLine(resultEOperationResult);
}
#endregion
}
//new
class ArchiveMemoryCallback : IArchiveExtractCallback
{
private uint FileNumber;
private Stream stream;
private OutStreamWrapper FileStream;
public ArchiveMemoryCallback(uint fileNumber, Stream stream)
{
this.FileNumber = fileNumber;
this.stream = stream;
}
#region IArchiveExtractCallback Members
public void SetTotal(ulong total)
{
}
public void SetCompleted(ref ulong completeValue)
{
}
public int GetStream(uint index, out ISequentialOutStream outStream, AskMode askExtractMode)
{
if ((index == FileNumber) && (askExtractMode == AskMode.kExtract))
{
FileStream = new OutStreamWrapper(stream);
outStream = FileStream;
}
else
outStream = null;
return 0;
}
public void PrepareOperation(AskMode askExtractMode)
{
}
public void SetOperationResult(OperationResult resultEOperationResult)
{
FileStream.Dispose();
Console.WriteLine(resultEOperationResult);
}
#endregion
}
}

Resources