I’m using metalsmith and create a plugin.
I am trying to change the contents, which is a Buffer type.
This is how the metalsmith-partials plugin is doing the same thing.
// get contents string
const contents = fileData.contents.toString();
// creates a new buffer using modified content string
fileData.contents = Buffer.from(contents.replace(markdownInclude.marker, markdownInclude.markerReplacement));
So I copied this code, yet instead of creating a Buffer object, it creates a UInt8Array object.
I am aware that a Buffer is a (subclass?) of UInt8Array but I want to create a Buffer.
How can I force my statement to actually give me a Buffer?
Related
After writing the content of the text file to the TStringList object, I try to change one character in the line and then write the entire content of the object back to the file. In the saved file, the changed line character was not saved as expected and is still unchanged. To write the change of character to the file I need to use the String object.
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TStringList *Lista = new TStringList;
if(OpenDialog1->Execute())
Lista->LoadFromFile(OpenDialog1->FileName);
Lista->Strings[0][1] = '0'; // this does not work
// Only this way work
String A = Lista->Strings[0];
A[1] = '0';
Lista->Strings[0] = A;
}
I don't understand why the sign change directly in the TStringList object doesn't happen, or if it does, why isn't it written to the file.
The TStringList::Strings[] property getter DOES NOT return a reference to a String object, like you are expecting. It returns a String object by value instead, which means a copy is returned as a temporary object.
Strings[0][1] = ... has no effect because you are modifying that temporary object and not assigning it anywhere afterwards, so it just goes out of scope immediately.
That is why you need to save that temporary object to a local variable first, and then assign that variable back to the Strings[] property after modifying the variable's data.
I want to read the contents of a file piece by piece through an interface (instead of reading the whole file at once with readAsBytes()). openRead() seems to do the trick, but it returns a List<int> type. And I expect it to be Uint8List, because I want to do block operations on some of the contents.
If you convert the returned List<int> to Uint8List, it seems to make a copy of the contents, which is a big loss in efficiency.
Is this how it was designed?
Historically Dart used List<int> for sequences of bytes before a more specific Uint8List class was added. A Uint8List is a subtype of List<int>, and in most cases where a Dart SDK function returns a List<int> for a list of bytes, it's actually a Uint8List object. You therefore usually can just cast the result:
var file = File('/path/to/some/file');
var stream = file.openRead();
await for (var chunk in stream) {
var bytes = chunk as Uint8List;
}
If you are uncomfortable relying on the cast, you can create a helper function that falls back to creating a copy if and only if necessary.
There have been efforts to change the Dart SDK function signatures to use Uint8List types explicitly, and that has happened in some cases (e.g. File.readAsBytes). Such changes would be breaking API changes, so they cannot be done lightly. I don't know why File.openRead was not changed, but it's quite likely that the amount of breakage was deemed to be not worth the effort. (At a minimum, the SDK documentation should be updated to indicate whether it is guaranteed to return a Uint8List object. Also see https://github.com/dart-lang/sdk/issues/39947)
Alternatively, instead of using File.openRead, you could use File.open and then use RandomAccessFile.read, which is declared to return a Uint8List.
I am using an instance of the IHTMLDocument2 interface to parse some HTML as described in this post:
Load from IPersistMoniker takes long time to load unresolvable URL
The code is relatively simple:
DelphiInterface<IHTMLDocument2> diDoc2;
HRESULT hr = CoCreateInstance(CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER, IID_IHTMLDocument2, (LPVOID*)&diDoc2);
// Load and process HTML here and save into memory stream or to disk after the processing is done
When I am done I save the HTML contents of the newly modified diDoc2 above and load the HTML into TWebBrowser.
Can I instead just "assign" the already parsed IHTMLDocument2 above directly to the IHTMLDocument2 contained in the TWebBrowser, which seems would be much faster way of doing it. I can use probably IHTMLDocument2.write or some other method to do so, but there would be likely some performance penalty than simply assigning a pointer to already initialized object, if that is possible in the first place. In other words, I simply want to "show"/"render" what I have just parsed in the "back buffer" of sort.
Is there a need to call CoInitialize and CoUninitialize before and after calling CoCreateInstance? I've seen some code which does that but it works without it, unless Delphi/C++ Builder do some under-the-hood initialization.
I used IHTMLDocument2.write and it appears to work well.
WideString HTML = "<html><body>test</body></html>";
if (diDoc)
{
// Creates a new one-dimensional array
SAFEARRAY *psaStrings = SafeArrayCreateVector(VT_VARIANT,0,1);
if (psaStrings)
{
VARIANT *param;
BSTR bstr = SysAllocString(HTML.c_bstr());
SafeArrayAccessData(psaStrings, (LPVOID*)¶m);
param->vt = VT_BSTR;
param->bstrVal = bstr;
SafeArrayUnaccessData(psaStrings);
diDoc->write(psaStrings);
diDoc->close();
// SafeArrayDestroy calls SysFreeString for each BSTR
//SysFreeString(bstr); // SafeArrayDestroy should be enough
SafeArrayDestroy(psaStrings);
return S_OK;
}
}
return E_FAIL;
In my VSIX project this error is shown on the line:
(AdapterService as IVsEditorAdaptersFactoryService).SetDataBuffer(textLines, projBuffer as IProjectionBuffer);
where textLines is created using CreateInstance method of my package
Type textLinesType = typeof(IVsTextLines);
Guid riid = textLinesType.GUID;
Guid clsid = typeof(VsTextBufferClass).GUID;
IVsTextLines textLines = (_package as Package).CreateInstance(ref clsid, ref riid, textLinesType) as IVsTextLines;
What actually is DocumentTextBuffer property and how do I set it on a newly instantiated IVsTextLines?
What I am trying to do is create a IVsTextLines to pass it as a buffer to IVsCodeWindow.
I changed the initialization of textLines to
textLines = AdapterService.CreateVsTextBufferAdapter(serviceProvider as IOleServiceProvider,
(contentTypeRegistry as IContentTypeRegistryService).GetContentType("csharp")) as IVsTextLines;
and then have used the IVsTextBuffer.InitializeContent method to initialize the Document and Data text buffer to a single space character. After that I was able to successfully use the SetBuffer method.
I am still haven't finalized my extension, so I am not sure how relevant Document Buffer's content is.
I have a site where I allow members to upload photos. In the MVC Controller I take the FormCollection as the parameter to the Action. I then read the first file as type HttpPostedFileBase. I use this to generate thumbnails. This all works fine.
In addition to allowing members to upload their own photos, I would like to use the System.Net.WebClient to import photos myself.
I am trying to generalize the method that processes the uploaded photo (file) so that it can take a general Stream object instead of the specific HttpPostedFileBase.
I am trying to base everything off of Stream since the HttpPostedFileBase has an InputStream property that contains the stream of the file and the WebClient has an OpenRead method that returns Stream.
However, by going with Stream over HttpPostedFileBase, it looks like I am loosing ContentType and ContentLength properties which I use for validating the file.
Not having worked with binary stream before, is there a way to get the ContentType and ContentLength from a Stream? Or is there a way to create a HttpPostedFileBase object using the Stream?
You're right to look at it from a raw stream perspective because then you can create one method that handles streams and therefore many scenarios from which they come.
In the file upload scenario, the stream you're acquiring is on a separate property from the content-type. Sometimes magic numbers (also a great source here) can be used to detect the data type by the stream header bytes but this might be overkill since the data is already available to you through other means (i.e. the Content-Type header, or the .ext file extension, etc).
You can measure the byte length of the stream just by virtue of reading it so you don't really need the Content-Length header: the browser just finds it useful to know what size of file to expect in advance.
If your WebClient is accessing a resource URI on the Internet, it will know the file extension like http://www.example.com/image.gif and that can be a good file type identifier.
Since the file info is already available to you, why not open up one more argument on your custom processing method to accept a content type string identifier like:
public static class Custom {
// Works with a stream from any source and a content type string indentifier.
static public void SavePicture(Stream inStream, string contentIdentifer) {
// Parse and recognize contentIdentifer to know the kind of file.
// Read the bytes of the file in the stream (while counting them).
// Write the bytes to wherever the destination is (e.g. disk)
// Example:
long totalBytesSeen = 0L;
byte[] bytes = new byte[1024]; //1K buffer to store bytes.
// Read one chunk of bytes at a time.
do
{
int num = inStream.Read(bytes, 0, 1024); // read up to 1024 bytes
// No bytes read means end of file.
if (num == 0)
break; // good bye
totalBytesSeen += num; //Actual length is accumulating.
/* Can check for "magic number" here, while reading this stream
* in the case the file extension or content-type cannot be trusted.
*/
/* Write logic here to write the byte buffer to
* disk or do what you want with them.
*/
} while (true);
}
}
Some useful filename parsing features are in the IO namespace:
using System.IO;
Use your custom method in the scenarios you mentioned like so:
From an HttpPostedFileBase instance named myPostedFile
Custom.SavePicture(myPostedFile.InputStream, myPostedFile.ContentType);
When using a WebClient instance named webClient1:
var imageFilename = "pic.gif";
var stream = webClient1.DownloadFile("http://www.example.com/images/", imageFilename)
//...
Custom.SavePicture(stream, Path.GetExtension(imageFilename));
Or even when processing a file from disk:
Custom.SavePicture(File.Open(pathToFile), Path.GetExtension(pathToFile));
Call the same custom method for any stream with a content identifer that you can parse and recognize.