Notifications
Clear all

[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?

7 Replies

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()
   
 lo1

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.

how many good methods to do something better than max does…

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.