[Closed] dotnet filestream read
Hi,
I’m having trouble reading a filestream with dotnet. Consider the following code
strPath = @“some path to a file on disk”
theStream = (dotNetClass “System.io.file”).open strPath (dotnetClass “system.io.filemode”).open –open a filestream
myBuffer = dotnetobject “System.Byte[]” 1024 –setup a bytearray as a temporary buffer with a size of 1024
theStream.read myBuffer 0 myBuffer.length –read a chunk of 1024 bytes out of the stream
theStream.close()
This code results in an error for me
– Runtime error: dotNet runtime exception: Buffer cannot be null
Parameter name: array
I’m not sure why this happens. The myBuffer variable has a length. Do I need to initialize it somehow?
you are doing everything right for me. the same works just fine in c#. but max passes something wrong in place of a byte array.
is it OK for your task to read all bytes?
<byte[]> = (dotNetClass "System.IO.File").ReadAllBytes <the file> asdotnetobject:on
another way is to make a little ‘on-fly’ assembly and use its methods:
fn CreateFileOpsAssembly =
(
source = ""
source += "using System;
"
source += "using System.Text;
"
source += "using System.IO;
"
source += "namespace FileOps
"
source += "{
"
source += " public class Stream
"
source += " {
"
source += " public int ReadFull(FileStream stream, byte[] buffer)
"
source += " {
"
source += " return stream.Read(buffer, 0, buffer.Length);
"
source += " }
"
source += " public int Read(FileStream stream, byte[] buffer, int offset, int count)
"
source += " {
"
source += " return stream.Read(buffer, offset, count);
"
source += " }
"
source += " }
"
source += "}
"
csharpProvider = dotnetobject "Microsoft.CSharp.CSharpCodeProvider"
compilerParams = dotnetobject "System.CodeDom.Compiler.CompilerParameters"
compilerParams.ReferencedAssemblies.AddRange #("System.dll")
compilerParams.GenerateInMemory = on
compilerResults = csharpProvider.CompileAssemblyFromSource compilerParams #(source)
assembly = compilerResults.CompiledAssembly
assembly.CreateInstance "FileOps.Stream"
)
global FileOpsStream = CreateFileOpsAssembly()
/*
stream = (dotNetClass "System.IO.File").OpenRead (getMAXIniFile())
buffer = dotnetobject "byte[]" 1024
FileOpsStream.ReadFull stream buffer
buffer.Clone()
stream.Close()
*/
maybe Invoke and Reflection will work well.
edit
checked… yes… it works:
stream = (dotNetClass "System.IO.File").OpenRead (getMAXIniFile())
buffer = dotnetobject "byte[]" 1024
type = stream.GetType()
bf = dotnetclass "System.Reflection.BindingFlags"
flags = dotnet.combineEnums bf.Public bf.Instance bf.InvokeMethod
type.InvokeMember "Read" flags type.DefaultBinder stream #(buffer, 0, buffer.Length)
buffer.Clone()
I suspect that MAXScript might be calling the wrong method.
MAXScript searches for method based on these reflection binding flags:
BindingFlags::Static | BindingFlags::Instance | BindingFlags::Public | BindingFlags::FlattenHierarchy
I have a hunch FlattehHierarchy might be returning Stream.Read instead of FileStream.Read.
To work around this, get the method yourself:
strPath = @"some path to a file on disk"
theStream = (dotNetClass "System.io.file").open strPath (dotnetClass "system.io.filemode").open --open a filestream
myBuffer = dotnetobject "System.Byte[]" 1024 --setup a bytearray as a temporary buffer with a size of 1024
readMethod = (theStream.GetType()).GetMethod "Read"
readMethod.invoke theStream #(myBuffer, 0, myBuffer.Length)
theStream.close()
edit: dammit Denis, I was in the middle of writing it
edit2: It’s not the bindingFlags that are the problem, I have no idea why max messes it up.
because you was writing where i was just simply coping and slightly modifying.
Thanks denisT and lo,
I think doing this task in chunks is a good idea since I’m uploading a file to a webservice. If I try to do the entire file at once I might run out of memory and I can’t update a progressbar as well.
Both the c# and getmethod/invoke methods look good to me. I’m going with the latter.