Load serialized data in multiple applications C# - c#

Scenario:
I have a program which uses a simple class to generate game data. Using the said program, I write the data out using serialization and BinaryFormatter to a file to be used by a second program. Reading the data from this initial program works without issue.
Problem:
It's probably down to my ignorance to how serialized files are handled, but I cannot then load this data into a second program, the actual game itself.
saveGame code (in program 1):
static List<GameData> gameData;
static GameData currentData;
private void saveGame(Sudoku sdk) {
BinaryFormatter bf = new BinaryFormatter();
FileStream file = null;
try {
if(!File.Exists(gameDataFile[currentDifficulty])) {
file = File.Open(gameDataFile[currentDifficulty], FileMode.CreateNew);
} else {
file = File.Open(gameDataFile[currentDifficulty], FileMode.Append);
}
currentData = setGameData(sdk);
bf.Serialize(file, currentData);
savePuzzleLog();
} catch(Exception e) {
Debug.LogException("saveGame", e);
}
if(file != null) {
file.Close();
}
}
loadGameData: (in program 2)
public static List<GameData> gameData;
public bool loadGameData() {
if(gameData == null) {
gameData = new List<GameData>();
} else {
gameData.Clear();
}
bool loadData = true;
bool OK = false;
if(File.Exists(gameDataFile[currentDifficulty])) {
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Open(gameDataFile[currentDifficulty], FileMode.Open);
while(loadData) {
try {
GameData gd = new GameData();
gd = (GameData)bf.Deserialize(file);
gameData.Add(gd);
OK = true;
if(file.Position == file.Length) {
loadData = false;
}
} catch(Exception e) {
Debug.LogException(e);
loadData = false;
OK = false;
}
}
if(file != null) {
file.Close();
}
} else {
Debug.LogWarning(gameDataFile[currentDifficulty] + " does not exist!");
}
return OK;
}
GameData Class: (1st program)
[Serializable]
class GameData {
private int gameID;
private List<int> contentArray;
private int difficultyValue;
public GameData(List<int> data = null) {
id = -1;
difficulty = -1;
if(content != null) {
content.Clear();
} else {
content = new List<int>();
}
if(data != null) {
foreach(int i in data) {
content.Add(i);
}
}
}
public int id {
get {
return this.gameID;
}
set {
this.gameID = value;
}
}
public int difficulty {
get {
return this.difficultyValue;
}
set {
this.difficultyValue = value;
}
}
public List<int> content {
get {
return this.contentArray;
}
set {
this.contentArray = value;
}
}
}
GameData Class: (2nd program) The only difference is declaring as public
[Serializable]
public class GameData {
private int gameID;
private List<int> contentArray;
private int difficultyValue;
public GameData(List<int> data = null) {
id = -1;
difficulty = -1;
if(content != null) {
content.Clear();
} else {
content = new List<int>();
}
if(data != null) {
foreach(int i in data) {
content.Add(i);
}
}
}
public int id {
get {
return this.gameID;
}
set {
this.gameID = value;
}
}
public int difficulty {
get {
return this.difficultyValue;
}
set {
this.difficultyValue = value;
}
}
public List<int> content {
get {
return this.contentArray;
}
set {
this.contentArray = value;
}
}
}
What my question is, is how do I save the data out in one program and be able to load it using a different program without getting serialization errors or do I need to use an alternate save/load method and/or class structure?

When I had to do it i made it this way :
An independant dll (assembly) containing the class holding the data (for you the GameData class), and utility methods to save/load from a file.
Your two other projects must then reference this dll (assembly) and you should be able to (de)serialize correctly.
What I think the issue is in your case is that the BinaryFormatter does not only save the data in the file, but also the complete Type of the serialized object.
When you try to deserialize in another similar object, even if the structure is the same, the full name of the class is not (because the assembly name is not).

OK, I've sorted it using the advice given. Instead of using BinaryFormatter I have used BinaryWriter and BinaryReader as follows...
In program 1 (the creator):
private byte[] setByteData(Sudoku sdk) {
List<int> clues = sdk.puzzleListData();
byte[] bd = new byte[puzzleSize];
SudokuSolver solver = new SudokuSolver();
List<int> solution = solver.Solve(sdk.Copy(), false, currentDifficulty).puzzleListData();
for(int i = 0; i < puzzleSize; i++) {
bd[i] = Convert.ToByte(solution[i] + (clues[i] == 0 ? 0xF0 : 0));
}
return bd;
}
private GameData setGameData(Sudoku sdk) {
List<int> clues = sdk.puzzleListData();
GameData gd = new GameData();
gd.id = puzzleList.Items.Count;
gd.difficulty = currentDifficulty;
SudokuSolver solver = new SudokuSolver();
List<int> solution = solver.Solve(sdk.Copy(), false, currentDifficulty).puzzleListData();
for(int i = 0; i < puzzleSize; i++) {
gd.content.Add(solution[i] + (clues[i] == 0 ? 0xF0 : 0));
}
return gd;
}
private List<int> getByteData(byte[] data) {
List<int> retVal = new List<int>();
foreach(byte i in data) {
if(i > 9) {
retVal.Add(i - 0xF0);
} else {
retVal.Add(0);
}
}
return retVal;
}
private string getGameData(List<int> data) {
string retVal = "";
foreach(int i in data) {
if(i > 9) {
retVal += (i - 0xF0).ToString();
} else {
retVal += i.ToString();
}
}
return retVal;
}
private void saveGame(Sudoku sdk) {
FileStream file = null;
BinaryWriter bw = null;
try {
if(!File.Exists(gameDataFile[currentDifficulty])) {
file = File.Open(gameDataFile[currentDifficulty], FileMode.CreateNew);
} else {
file = File.Open(gameDataFile[currentDifficulty], FileMode.Append);
}
bw = new BinaryWriter(file);
currentData = setGameData(sdk);
byte[] bd = setByteData(sdk);
bw.Write(currentData.id);
bw.Write(currentData.difficulty);
bw.Write(bd);
savePuzzleLog();
} catch(Exception e) {
Debug.LogException("saveGame", e);
}
if(file != null) {
if(bw != null) {
bw.Flush();
bw.Close();
}
file.Close();
}
}
In program 2: (the actual game)
public bool loadGameData() {
if(gameData == null) {
gameData = new List<GameData>();
} else {
gameData.Clear();
}
bool loadData = true;
bool OK = false;
if(File.Exists(gameDataFile[currentDifficulty])) {
FileStream file = File.Open(gameDataFile[currentDifficulty], FileMode.Open);
BinaryReader br = new BinaryReader(file);
while(loadData) {
try {
GameData gd = new GameData();
gd.id = br.ReadInt32();
gd.difficulty = br.ReadInt32();
gd.content = getByteData(br.ReadBytes(puzzleSize));
gameData.Add(gd);
OK = true;
if(file.Position == file.Length) {
loadData = false;
}
} catch(Exception e) {
Debug.LogException(e);
loadData = false;
OK = false;
}
}
if(file != null) {
file.Close();
}
} else {
Debug.LogWarning(gameDataFile[currentDifficulty] + " does not exist!");
}
return OK;
}
The class structure is the same as before but using this method has resolved my issue and I can now create the data files using my creator and load the data comfortably using the actual game.
Thanks all for your assistance and advice to help me get this sorted.

Related

Serialize and Deserialize list of object, without break encapsulation

I have a class called Member that I want to save and load in a XML file.
Here is my methods to load/save
public T LoadGenericDataType<T>(string filename)
{
XmlSerializer xms = new XmlSerializer(typeof(T));
FileStream fileStream = new FileStream(this._rootFolder + filename, FileMode.Open, FileAccess.ReadWrite);
try
{
Object v = xms.Deserialize(fileStream);
fileStream.Close();
return (T) v;
}
catch (Exception e)
{
fileStream.Close();
throw e;
}
}
public bool SaveGenericDataType<T>(T data, string filename)
{
XmlSerializer xms = new XmlSerializer(typeof(T));
FileStream fileStream = new FileStream(this._rootFolder + filename, FileMode.Create, FileAccess.Write);
try
{
xms.Serialize(fileStream, data);
fileStream.Close();
return true;
}
catch (Exception e)
{
fileStream.Close();
return false;
}
}
In my member class I save a property called Boats, and I don't want to send the original List to any other class so I do a copy of it.
public List<Boat> Boats
{
get => _boats; // this will break encapsulation, but will make it easier to serialize( bad design my me :/ )
set => _boats = value;
}
public List<Boat> Boats1
{
get
{
List<Boat> copyOfBoats = new List<Boat>(); // this will cause LOADING to fail not saving.
foreach (Boat boat in _boats)
{
copyOfBoats.Add(boat);
}
return copyOfBoats;
}
set => _boats = value;
}
What am I missing? If I try to load an xml with the "Boats1" Property it will fail.
Okay I managed to fixed the problem by this.
public List<Boat> Boats
{
get
{
if (_boats.Count == 0)
return _boats;
List<Boat> copyOfBoats = new List<Boat>(); .
foreach (Boat boat in _boats)
{
copyOfBoats.Add(boat);
}
return copyOfBoats;
}
set => _boats = value;
}
But it will still break encapsulation if the member don't have any boats.
Maybe try
public List<Boat> Boats1
{
get
{
List<Boat> copyOfBoats = new List<Boat>();
if (_boats.Count > 0)
{
foreach (Boat boat in _boats)
{
copyOfBoats.Add(boat);
}
}
return copyOfBoats;
}
set => _boats = value;
}
That should keep it from returning the orginal list of boats.

C# Class Properties 'tied' to a file? (See Perl::Tie)

In perl there's a rather simple method of tying a data structure to a file, whether it be a string, hash(dictionary in C#) or a simple array/list.
I've cobbled together my own half-assed solution in C# but I was wondering if there's a more inbuilt way to achieve this functionality?
Edit in response to comment below--The question, directly: Is there an inbuilt way to "tie" a class/dictionary to a file so any changes in either is reflected in the other? (Without doing as I've done below)
(Tieing a dictionary means that any changes in the dictionary are immediately reflected/updated in the file and declaring a tied var loads the object from disk if it already exists; see PerlTie )
My pseudo-tie'd class is below:
#region options
private float _Opacity;
public float Opacity {
get {
return Opacity;
}
set {
_Opacity = value;
this.Save();
}
}
private Font _Font;
public Font Font {
get {
return _Font;
}
set {
_Font = value;
this.Save();
}
}
private Color _FontColor;
public Color FontColor {
get {
return _FontColor;
}
set {
_FontColor = value;
this.Save();
}
}
private Color _BGColor;
public Color BGColor {
get {
return _BGColor;
}
set {
_BGColor = value;
this.Save();
}
}
private Point _Location;
public Point Location {
get {
return _Location;
}
set {
_Location = value;
this.Save();
}
}
private Size _Size;
public Size Size {
get {
return _Size;
}
set {
_Size = value;
this.Save();
}
}
private ushort _HistoryLines;
public ushort HistoryLines {
get {
return _HistoryLines;
}
set {
_HistoryLines = value;
this.Save();
}
}
private ChatType _ChatModes;
public ChatType ChatModes {
get {
return _ChatModes;
}
set {
_ChatModes = value;
this.Save();
}
}
private bool _Debugging;
public bool Debugging {
get {
return _Debugging;
}
set {
_Debugging = value;
this.Save();
}
}
#endregion options
private FontConverter FontConvert;
private FileInfo SettingsFile;
private MLogConf() {
}
public MLogConf(string stateFile) {
FontConvert = new FontConverter();
try {
if (!Directory.Exists(Path.GetDirectoryName(stateFile)))
Directory.CreateDirectory(Path.GetDirectoryName(stateFile));
if (!File.Exists(stateFile)) {
FileStream fs = File.Create(stateFile);
fs.Close();
}
SettingsFile = new FileInfo(stateFile);
if (SettingsFile.Length == 0) {
this.SetDefaultOptions();
} else {
if (!this.Load()) {
throw new FileLoadException("Couldn't load settings file");
}
}
} catch (Exception ex) {
Trace.Write($"Failed to create MLogConf({nameof(stateFile)}) {ex.Message + Environment.NewLine + ex.StackTrace}");
}
}
private bool Load() {
if (SettingsFile == null)
return false;
try {
byte[] data = File.ReadAllBytes(SettingsFile.FullName);
using (MemoryStream m = new MemoryStream(data)) {
using (BinaryReader reader = new BinaryReader(m)) {
_Opacity = reader.ReadSingle();
_Font = (Font)(FontConvert.ConvertFromString(Encoding.ASCII.GetString(Convert.FromBase64String(reader.ReadString()))));
_FontColor = Color.FromArgb(reader.ReadInt32());
_BGColor = Color.FromArgb(reader.ReadInt32());
_Location = new Point(reader.ReadInt32(), reader.ReadInt32());
_Size = new Size(reader.ReadInt32(), reader.ReadInt32());
_HistoryLines = reader.ReadUInt16();
_ChatModes = (ChatType)reader.ReadInt32();
_Debugging = reader.ReadBoolean();
}
}
} catch (Exception e) {
Trace.WriteLine($"Exception reading binary data: {e.Message + Environment.NewLine + e.StackTrace}");
return false;
}
return true;
}
private bool Save() {
try {
using (FileStream fs = new FileStream(SettingsFile.FullName, FileMode.Create)) {
using (BinaryWriter writer = new BinaryWriter(fs)) {
writer.Write(_Opacity);
writer.Write(Convert.ToBase64String(Encoding.ASCII.GetBytes((string)FontConvert.ConvertTo(Font, typeof(string)))));
writer.Write(_FontColor.ToArgb());
writer.Write(_BGColor.ToArgb());
writer.Write(_Location.X);
writer.Write(_Location.Y);
writer.Write(_Size.Width);
writer.Write(_Size.Height);
writer.Write(_HistoryLines);
writer.Write((int)_ChatModes);
writer.Write(_Debugging);
}
}
} catch (Exception e) {
Trace.WriteLine($"Exception writing binary data: {e.Message + Environment.NewLine + e.StackTrace}");
return false;
}
return true;
}
private bool SetDefaultOptions() {
this._BGColor = Color.Black;
this._ChatModes = ChatType.Alliance | ChatType.Emote | ChatType.FreeCompany | ChatType.Linkshell | ChatType.Party | ChatType.SayShoutYell | ChatType.Tell;
this._Opacity = 1f;
this._Font = new Font("Verdana", 50);
this._FontColor = Color.CornflowerBlue;
this._Location = new Point(100, 400);
this._Size = new Size(470, 150);
this._HistoryLines = 512;
this._Debugging = false;
return this.Save();
}
I suppose you are looking for an easy way to store class instances in files.
Serialization is the process of converting an object into a stream of bytes in order to store the object or transmit it to memory, a database, or a file. Its main purpose is to save the state of an object in order to be able to recreate it when needed. The reverse process is called deserialization.
The shortest solution I've found for C# here some time ago was Json.NET from Newtonsoft, available as NuGet package. It will do all the 'long class-properties-to-string code' for you and leave you with string ready to be written in file.
Official site can provide code examples: http://www.newtonsoft.com/json
Save to file:
Product product = new Product();
product.Name = "Apple";
product.Expiry = new DateTime(2008, 12, 28);
product.Sizes = new string[] { "Small" };
string json = JsonConvert.SerializeObject(product);
// {
// "Name": "Apple",
// "Expiry": "2008-12-28T00:00:00",
// "Sizes": [
// "Small"
// ]
// }
Read from file:
string json = #"{
'Name': 'Bad Boys',
'ReleaseDate': '1995-4-7T00:00:00',
'Genres': [
'Action',
'Comedy'
]
}";
Movie m = JsonConvert.DeserializeObject<Movie>(json);
string name = m.Name;
// Bad Boys

I am trying to access data in a C# packet I've created, however I keep getting null as a response. What am I doing wrong?

Okay, so I'm working with custom network code for pretty much the first time. I have a packet created to transfer some game information back and forth, however beyond the initial content if I try to access some of the commands, I get "null" - though on the server side, it's showing as properly populated.
I have a feeling that this has to do with the setup in receiving the data. The code for the packet follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
public enum DataIdentifier
{
Message,
Command,
LogIn,
LogOut,
Null
}
public class Packet
{
private DataIdentifier dataIdentifier;
private string name;
private string player;
private string playerData;
private string message;
private string command;
private string x;
private string y;
private string z;
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
public string Player
{
get
{
return player;
}
set
{
player = value;
}
}
public string Message
{
get
{
return message;
}
set
{
message = value;
}
}
public string Command
{
get
{
return command;
}
set
{
command = value;
}
}
public DataIdentifier DataIdentifier
{
get
{
return dataIdentifier;
}
set
{
dataIdentifier = value;
}
}
public string PlayerData
{
get
{
return playerData;
}
set
{
playerData = value;
}
}
public string X
{
get
{
return x;
}
set
{
x = value;
}
}
public string Y
{
get
{
return y;
}
set
{
y = value;
}
}
public string Z
{
get
{
return z;
}
set
{
z = value;
}
}
public Packet()
{
this.DataIdentifier = DataIdentifier.Null;
this.message = null;
this.name = null;
this.player = null;
this.playerData = null;
this.x = null;
this.y = null;
this.z = null;
this.command = null;
}
public Packet(byte[] dataStream)
{
// Read the data identifier from the beginning of the stream (4 bytes)
this.DataIdentifier = (DataIdentifier)BitConverter.ToInt32(dataStream, 0);
// Read the length of the name (4 bytes)
int nameLength = BitConverter.ToInt32(dataStream, 4);
// Read the length of the message (4 bytes)
int msgLength = BitConverter.ToInt32(dataStream, 8);
// Read the name field
if (nameLength > 0)
this.name = Encoding.UTF8.GetString(dataStream, 12, nameLength);
else
this.name = null;
// Read the message field
if (msgLength > 0)
this.message = Encoding.UTF8.GetString(dataStream, 12 + nameLength, msgLength);
else
this.message = null;
}
public byte[] GetDataStream()
{
List<byte> dataStream = new List<byte>();
// Add the dataIdentifier
dataStream.AddRange(BitConverter.GetBytes((int)this.DataIdentifier));
// Add the name length
if (this.name != null)
dataStream.AddRange(BitConverter.GetBytes(this.name.Length));
else
dataStream.AddRange(BitConverter.GetBytes(0));
// Add the message length
if (this.message != null)
dataStream.AddRange(BitConverter.GetBytes(this.message.Length));
else
dataStream.AddRange(BitConverter.GetBytes(0));
// Add the name
if (this.name != null)
dataStream.AddRange(Encoding.UTF8.GetBytes(this.name));
// Add the message
if (this.message != null)
dataStream.AddRange(Encoding.UTF8.GetBytes(this.message));
if (this.playerData != null)
{
dataStream.AddRange(Encoding.UTF8.GetBytes(this.playerData));
}
if (this.command != null)
{
dataStream.AddRange(Encoding.UTF8.GetBytes(this.command));
}
if (this.x != null)
{
dataStream.AddRange(Encoding.UTF8.GetBytes(this.x));
}
if (this.y != null)
{
dataStream.AddRange(Encoding.UTF8.GetBytes(this.y));
}
if (this.z != null)
{
dataStream.AddRange(Encoding.UTF8.GetBytes(this.z));
}
return dataStream.ToArray();
}
}
This is how the packet is recieved:
// Receive all data
this.clientSocket.EndReceive(AR);
// Initialise a packet object to store the received data
Packet receivedData = new Packet(this.dataStream);
// Evaulate command played
if (PacketDelegate != null)
{
PacketDelegate(receivedData);
}
// Reset data stream
this.dataStream = new byte[8142];
// Continue listening for broadcasts
clientSocket.BeginReceiveFrom(this.dataStream, 0, this.dataStream.Length, SocketFlags.None, ref epServer, new AsyncCallback(this.ReceiveCallback), null);
And this is the delegate function responsible for handling a packet:
public void RecievePacket(Packet Communication)
{
// Check and manipulate the contents of the packet here //
}
I have confirmed that I can get name, DataIdentifier, and Message, but it's the additional information I've added to the packet itself - player/data, command, x,y,z, I can't seem to get.
My thought is that the problem exists in establishing Packet(byte[] dataStream). However, I'm not quite sure how to calculate or add the additional variables to this. Can anyone give me some tips on how to do so?

SharpDXException on setting Shader inputLayout

This didnt used to throw this exception but now it does
if (shader.ShaderInput == null) shader.ShaderInput = new InputLayout(OneEngineInstance.EngineInstance.Device, ShaderSignature.GetInputSignature(shader.CompilationResult), new[] { new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), new InputElement("COLOR", 0, Format.R32G32B32_Float, 16, 0) });
The only useful information it gives me is
An unhandled exception of type 'SharpDX.SharpDXException' occurred in SharpDX.dll
Additional information: HRESULT: [0x80070057], Module: [General], ApiCode: [E_INVALIDARG/Invalid Arguments], Message: The parameter is incorrect.
Im not sure why this is doing this and im still pretty new to SharpDX
AssetsLoader.cs
using System;
using System.IO;
using SharpDX;
using SharpDX.DXGI;
using SharpDX.Direct3D;
using SharpDX.Direct3D11;
using SharpDX.D3DCompiler;
using SharpDX.XAudio2;
using SharpDX.Multimedia;
using OneEngine.DataTypes;
using OneEngine.Core;
namespace OneEngine.Assets
{
public static class AssetsLoader
{
public static void LoadImage(Image image)
{
image.Texture = Texture2D.FromFile<Texture2D>(OneEngineInstance.EngineInstance.Device, image.FilePath);
image.ShaderResourceView = new ShaderResourceView(OneEngineInstance.EngineInstance.Device, image.Texture);
image.Sampler = new SamplerState(OneEngineInstance.EngineInstance.Device, new SamplerStateDescription()
{
// TODO > Make Simplifier classes for these values and adapt to engine settings
Filter = Filter.MinMagMipLinear,
AddressU = TextureAddressMode.Wrap,
AddressV = TextureAddressMode.Wrap,
AddressW = TextureAddressMode.Wrap,
BorderColor = Color.Black,
ComparisonFunction = Comparison.Never,
MaximumAnisotropy = 16,
MipLodBias = 0,
MinimumLod = 0,
MaximumLod = 16
});
}
public static void LoadShader(Shader shader)
{
for (int i = 0; i < shader.ShaderTypes.Length; i++)
{
switch (shader.ShaderTypes[i])
{
case EShaderType.VERTEX:
shader.CompilationResult = ShaderBytecode.CompileFromFile(shader.FilePath, "VS", "vs_5_0");
shader.VertexShader = new VertexShader(OneEngineInstance.EngineInstance.Device, shader.CompilationResult);
break;
case EShaderType.PIXEL:
shader.CompilationResult = ShaderBytecode.CompileFromFile(shader.FilePath, "PS", "ps_5_0");
shader.PixelShader = new PixelShader(OneEngineInstance.EngineInstance.Device, shader.CompilationResult);
break;
case EShaderType.GEOMETRY:
shader.CompilationResult = ShaderBytecode.CompileFromFile(shader.FilePath, "GS", "gs_5_0");
shader.GeometryShader = new GeometryShader(OneEngineInstance.EngineInstance.Device, shader.CompilationResult);
break;
case EShaderType.COMPUTE:
shader.CompilationResult = ShaderBytecode.CompileFromFile(shader.FilePath, "CS", "cs_5_0");
shader.ComputeShader = new ComputeShader(OneEngineInstance.EngineInstance.Device, shader.CompilationResult);
break;
case EShaderType.DOMAIN:
shader.CompilationResult = ShaderBytecode.CompileFromFile(shader.FilePath, "DS", "ds_5_0");
shader.DomainShader = new DomainShader(OneEngineInstance.EngineInstance.Device, shader.CompilationResult);
break;
case EShaderType.HULL:
shader.CompilationResult = ShaderBytecode.CompileFromFile(shader.FilePath, "HS", "hs_5_0");
shader.HullShader = new HullShader(OneEngineInstance.EngineInstance.Device, shader.CompilationResult);
break;
}
}
if (shader.ShaderInput == null) shader.ShaderInput = new InputLayout(OneEngineInstance.EngineInstance.Device, ShaderSignature.GetInputSignature(shader.CompilationResult), new[] { new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0), new InputElement("COLOR", 0, Format.R32G32B32_Float, 16, 0) });
}
public static void LoadAudio(Audio audio)
{
audio.Stream = new SoundStream(File.OpenRead(audio.FilePath));
audio.Format = audio.Stream.Format;
audio.Buffer = new AudioBuffer
{
Stream = audio.Stream.ToDataStream(), AudioBytes = (int)audio.Stream.Length, Flags = BufferFlags.EndOfStream
};
audio.Stream.Close();
audio.Voice = new SourceVoice(AudioCore.XAudio, audio.Format, true);
if (audio.IsLoopable) audio.Buffer.LoopCount = audio.LoopTimes;
}
public static void LoadVideo()
{
}
public static void LoadFont()
{
}
public static void LoadLanguage()
{
}
}
public enum EShaderType
{
VERTEX, PIXEL, GEOMETRY, COMPUTE, DOMAIN, HULL
}
}
Shader.cs
using System;
using SharpDX.Direct3D;
using SharpDX.Direct3D11;
using SharpDX.D3DCompiler;
using OneEngine.Assets;
namespace OneEngine.DataTypes
{
public sealed class Shader
{
private String filePath;
private EShaderType[] shaderTypes;
private CompilationResult shaderByteCode;
private VertexShader vs;
private PixelShader ps;
private GeometryShader gs;
private ComputeShader cs;
private DomainShader ds;
private HullShader hs;
private InputLayout shaderInput;
private InputElement[] inputElements;
public Shader(String shaderFilePath, EShaderType[] types, InputElement[] elemets)
{
this.filePath = shaderFilePath;
this.shaderTypes = types;
this.inputElements = elemets;
}
public void RemoveFromMemory()
{
if (shaderByteCode != null) shaderByteCode.Dispose();
if (vs != null) vs.Dispose();
if (ps != null) ps.Dispose();
if (gs != null) gs.Dispose();
if (cs != null) cs.Dispose();
if (ds != null) ds.Dispose();
if (hs != null) hs.Dispose();
}
public String FilePath
{
get { return filePath; }
}
public EShaderType[] ShaderTypes
{
get { return shaderTypes; }
set { shaderTypes = value; }
}
public CompilationResult CompilationResult
{
get { return shaderByteCode; }
set { shaderByteCode = value; }
}
public VertexShader VertexShader
{
get { return vs; }
set { vs = value; }
}
public PixelShader PixelShader
{
get { return ps; }
set { ps = value; }
}
public GeometryShader GeometryShader
{
get { return gs; }
set { gs = value; }
}
public ComputeShader ComputeShader
{
get { return cs; }
set { cs = value; }
}
public DomainShader DomainShader
{
get { return ds; }
set { ds = value; }
}
public HullShader HullShader
{
get { return hs; }
set { hs = value; }
}
public InputLayout ShaderInput
{
set { shaderInput = value; }
get { return shaderInput; }
}
public InputElement[] ShaderInputElements
{
get { return inputElements; }
}
}
}
If you need anything else, the project is open source https://github.com/TheNanonNetwork/OneGames
Try creating your Graphics Device with DeviceCreationFlags.Debug and if the input layout is failing to create properly, then it'll tell you why.
Also, are you sure your Color attribute is supposed to be at an offset of 16 bytes given that the attribute before it is only 12 bytes in size?

database corruption error while copying database monodroid

I was developing android app on eclipse till now and now I'm using Mono for Android.
I am trying to copy the database from Assets folder, copy it onto the SD Card, then read data from it. I'm using the following code for the same. However I'm getting database corruption error.
After running the following code, empty database is getting created on SD card but the actual table is not getting copied.
Also how to check SD card content in MonoDevelop. I'm currently using eclipse for the same.
As I'm just beginner to android development, any help appreciated.
public class DbManager
{
private Context ctx;
private SQLiteDatabase mDb;
private DatabaseHelper dataHelper;
private String DATABASE_PATH = "/data/data/HelloM4A.HelloM4A/databases/";
private static String DATABASE_NAME = "CompanyMaster.db";
private SQLiteCursor cur;
private String[] b1;
private int x;
private static int DATABASE_VERSION = 1;
public DbManager(Context ctx)
{
this.ctx = ctx;
dataHelper = new DatabaseHelper(ctx);
}
private class DatabaseHelper : Android.Database.Sqlite.SQLiteOpenHelper
{
public DatabaseHelper AnyName
{ get; set; }
Context myContext = null;
public DatabaseHelper(Context context)
: base(context, DATABASE_NAME, null, DATABASE_VERSION)
{
this.myContext = context;
}
public override void OnCreate(Android.Database.Sqlite.SQLiteDatabase db)
{
}
public override void OnUpgrade(Android.Database.Sqlite.SQLiteDatabase db,
int oldVersion, int newVersion)
{
OnCreate(db);
}
}
public bool checkDataBase()
{
String myPath = DATABASE_PATH + DATABASE_NAME;
Java.IO.File f = new Java.IO.File(myPath);
return f.Exists();
}
public void createDataBase()
{
openDB();
try
{
Stream stream;
string destPath = Path.Combine(Environment.GetFolderPath(
Environment.SpecialFolder.Personal), "CompanyMaster.db");
if (new Java.IO.File(destPath).Exists())
using (stream = ctx.Assets.Open("CompanyMaster.db"))
{
OutputStream myOutput = new FileOutputStream(DATABASE_PATH +
DATABASE_NAME);
byte[] buffer = new byte[1024];
int length;
while ((length = stream.Read(buffer, 0, 1024)) > 0)
{
myOutput.Write(buffer, 0, length);
}
if (mDb.IsOpen == true)
mDb.Close();
myOutput.Flush();
myOutput.Close();
stream.Close();
}
}
catch (Exception e)
{ }
}
public DbManager openDB()
{
try
{
mDb = dataHelper.WritableDatabase;
}
catch (Exception e)
{ }
return this;
}
public String[] getSymbol()
{
try
{
cur = (SQLiteCursor)mDb.RawQuery("select symbol, company_name " +
"from Scrip", null);
}
catch (SQLiteException e)
{ }
b1 = new String[2168];
x = 0;
if (cur.MoveToFirst())
{
do`
{
b1[x] = cur.GetString(cur.GetColumnIndex("symbol"));
x++;
}
while (cur.MoveToNext());
}
cur.Close();
return b1;
}
public void close()
{
mDb.Close();
}
}
EDIT
After various suggestions, I tried following code :
public void createDataBase()
{
openDB();
try
{
var dataFile = ctx.ApplicationContext
.GetDatabasePath(DATABASE_NAME)
.AbsolutePath;
Console.WriteLine("path="+
ctx.ApplicationContext
.GetDatabasePath(DATABASE_NAME)
.AbsolutePath);
// I get path=/data/data/HelloM4A.HelloM4A/databases/CompanyMaster.db
// which is correct.
if (!System.IO.File.Exists(dataFile))
{
using (var input = ctx.Assets.Open(DATABASE_NAME))
using (var output = System.IO.File.Create(dataFile))
{
var buffer = new byte[1024];
int len;
while ((len = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, len);
}
}
}
}
catch
{
}
}
public DbManager openDB()
{
try
{
mDb = dataHelper.WritableDatabase;
}
catch
{
}
return this;
}
Now the issue is if I don't use openDB() within createDataBase() , it gives fileNotFoundException.
and if I use openDB() within createDataBase(), it created empty DB and hence DB doesn't get copied and I get Blank DB as final ouput because of following condition if (!System.IO.File.Exists(dataFile)).
Since already empty DB is created it doesn't traverse inside if.
What can be done here?
I use this code to copy out of the assets folder to where I want it (you should be able to modify it to suit yourself):
const string dbName = "evolution.sqlite";
var dataDirectory = Path.Combine(ApplicationContext.FilesDir.AbsolutePath,
"databases");
var dataFile = Path.Combine(dataDirectory, dbName);
if (!Directory.Exists(dataDirectory))
{
Directory.CreateDirectory(dataDirectory);
}
if (!File.Exists(dataFile))
{
using (var input = ApplicationContext.Assets.Open(dbName))
using (var output = File.Create(dataFile))
{
var buffer = new byte[1024];
int len;
while ((len = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, len);
}
}
}
Note: I dynamically create the path as I am using an ORM instead of the DB helper classes.
You could use dataDirectory = context.GetDatabasePath("").AbsolutePath(); instead.
You must do this before you use the DatabaseHelper as the database will also try and create the database. I do this in my Activity.OnCreate(...) method and then use the DatabaseHelper afterwards.
Thus, if my code was in a function called CopyDB(...) you use the method:
public DbManager openDB()
{
CopyDB(...);
try
{
mDb = dataHelper.WritableDatabase;
}
catch(Exception e)
{
}
return this;
}

Categories