尝试为我自己的XML样式文件格式编写解析器,获取FileNotFoundException,是否有什么特别是我做错了?

时间:2013-02-13 20:43:41

标签: java xml parsing xml-parsing filenotfoundexception

基本上,我正在尝试编写一个二维骨架动画编辑器以及一个框架,以便轻松使用游戏编辑器中创建的相同动画。最大的问题是我之前没有写过XML解析器,所以我觉得我可能做的事情完全错了,但我不确定它是什么。

以下是我格式的示例文件:

<skeleton name="skeleton1">

    <bones>
        <bone name="bone1" id="1" textureLoc="/imgs/test.png">
            <position>x,y</position>
            <rotation>float</rotation>
            <scale>float</scale>
        </bone>

        <bone name="bone2" id="2" textureLoc="/imgs/text2.png">
            <position>x,y</position>
            <rotation>float</rotation>
            <scale>float</scale>
        </bone>
    </bones>

    <animation name="anim1">
        <keyframe frameToPlay="1">
            <bone id="1" transPosition="x,y" transRotation="float" transScale="float">
            </bone>

            <bone id="2" transPosition="x,y" transRotation="float" transScale="float">
            </bone>
        </keyframe>

        <keyframe frameToPlay="50">
            <bone id="1" transPosition="x,y" transRotation="float" transScale="float">
            </bone>

            <bone id="2" transPosition="x,y" transRotation="float" transScale="float">
            </bone>
        </keyframe>
    </animation>

    <animation name="anim2">
        <keyframe frameToPlay="1">
            <bone id="1" transPosition="x,y" transRotation="float" transScale="float">
            </bone>

            <bone id="2" transPosition="x,y" transRotation="float" transScale="float">
            </bone>
        </keyframe>

        <keyframe frameToPlay="50">
            <bone id="1" transPosition="x,y" transRotation="float" transScale="float">
            </bone>

            <bone id="2" transPosition="x,y" transRotation="float" transScale="float">
            </bone>
        </keyframe>
    </animation>
</skeleton>



以下是我组织此系统的方式的说明,如果它使我的代码更容易理解:

AnimationSystem – Management interface for all animations in game, handles updating of each skeleton
--List of skeletons
---Skeletons represent each object
--Update method that updates each skeleton with the game’s current frame
Animation
--List of keyframes
--List of frames, in ascending order, pulled from the list of keyframes
---Order index in list corresponds to order index in list of keyframes
---Should help to speed things up a little bit, no need to search every keyframe to determine which one has a frame value matching the one that is currently needed.
---Will be determined by a set up method after assets are loaded, but before the animation can be used.
--Method to return a keyframe that corresponds to a frame passed to the method
Skeleton
--List of animations
--List of bones
--Value to hold the currently selected animation
--Value to hold the current frame in the game
--Value to hold the name of the skeleton
--Upon moving to a new frame, searches currently selected animation’s list of frames to see if a keyframe should be “played” this frame. If a keyframe exists that should be played at this frame, it should go through each bone in its list of bones, and set the properties of each bone to the properties listed in the keyframe according to the bone’s id.
Bone
--Value to hold the stationary position
--Value to hold the stationary rotation
--Value to hold the stationary scale
--Value to hold the transformed position
--Value to hold the transformed rotation
--Value to hold the transformed scale
--Image value that holds the texture of the bone
--Value to hold the id of the bone within its skeleton
--Value to hold the name of the bone (Used in the editor)
--Method that takes 3 values (position, rotation and scale in that order) and set’s its own transformed pos, rot and scale values to those passed in.
Keyframe
--List of scale values
--List of position values
--List of rotation values
--List of bone ids
---Index of bone id in list matches up to index in scale, position and rotation lists so that the properties can be associated with the bone
--Time value at which the keyframe will be played
--Method to return the scale value of a bone as determined by the bone id passed in
--Method to return the position value of a bone as determined by the bone id passed in
--Method to return the rotation value of a bone as determined by the bone id passed in



我为尝试解析此代码而编写的关联方法如下:

public static Skeleton parseSkeletonFile(String location) throws FileNotFoundException, IOException
    {
        try
        {
            Skeleton skelToReturn = null;

            File fileToLoad = new File(location);

            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            Document doc = dBuilder.parse(fileToLoad);

            doc.getDocumentElement().normalize();

            NodeList skelList = doc.getElementsByTagName("skeleton");

            for (int counter = 0; counter < skelList.getLength(); counter++)
            {
                Node skelNode = skelList.item(counter);

                Element skelElement = (Element)skelNode;

                skelToReturn = new Skeleton(skelElement.getAttribute("name"));

                NodeList allNodes = skelNode.getChildNodes();

                for (int counter2 = 0; counter2 < allNodes.getLength(); counter2++)
                {
                    Node currentNode = allNodes.item(counter2);

                    if (currentNode.getNodeName() == "bones")
                    {
                        NodeList bonesNL = currentNode.getChildNodes();

                        for (int counter3 = 0; counter3 < bonesNL.getLength(); counter3++)
                        {
                            Node currentBone = bonesNL.item(counter3);
                            Element currentBoneE = (Element)currentBone;

                            Bone bone = new Bone(
                                    currentBoneE.getAttribute("name"),
                                    new Point(
                                        Float.valueOf(currentBoneE.getElementsByTagName("position").item(0).getTextContent().split(",")[0]),
                                        Float.valueOf(currentBoneE.getElementsByTagName("position").item(0).getTextContent().split(",")[1])
                                        ),
                                    Float.valueOf(currentBoneE.getElementsByTagName("rotation").item(0).getTextContent()),
                                    Float.valueOf(currentBoneE.getElementsByTagName("scale").item(0).getTextContent()),
                                    Integer.valueOf(currentBoneE.getAttribute("id"))
                                    );



                            bone.setImage(new Image(currentBoneE.getAttribute("textureLoc")));

                            skelToReturn.bones.add(bone);
                        }
                    }

                    if (currentNode.getNodeName() == "animation")
                    {
                        NodeList animsNL = currentNode.getChildNodes();

                        for (int counter4 = 0; counter4 < animsNL.getLength(); counter4++)
                        {
                            Node currentAnim = animsNL.item(counter4);
                            Element currentAnimE = (Element)currentAnim;

                            Animation animation = new Animation(currentAnimE.getAttribute("name"));

                            NodeList keyframesNL = currentAnim.getChildNodes();

                            for (int counter5 = 0; counter5 < keyframesNL.getLength(); counter5++)
                            {
                                Node currentKeyframe = keyframesNL.item(counter5);
                                Element currentKeyframeE = (Element)currentKeyframe;

                                Keyframe keyframe = new Keyframe(Integer.valueOf(currentKeyframeE.getAttribute("frameToPlay")));

                                NodeList kfBonesNL = currentKeyframe.getChildNodes();

                                for (int counter6 = 0; counter6 < kfBonesNL.getLength(); counter6++)
                                {
                                    Node currentBoneTrans = kfBonesNL.item(counter6);
                                    Element currentBoneTransE = (Element)currentBoneTrans;

                                    keyframe.boneIDs.add(Integer.valueOf(currentBoneTransE.getAttribute("id")));
                                    keyframe.positions.add(new Point(Float.valueOf(currentBoneTransE.getAttribute("transPosition").split(",")[0]), Float.valueOf(currentBoneTransE.getAttribute("transPosition").split(",")[1])));
                                    keyframe.rotations.add(Float.valueOf(currentBoneTransE.getAttribute("transRotation")));
                                    keyframe.scales.add(Float.valueOf(currentBoneTransE.getAttribute("transScale")));
                                }
                                animation.keyframes.add(keyframe);
                                animation.frames.add(keyframe.getTimeToBePlayed());
                            }

                            skelToReturn.animations.add(animation);
                            skelToReturn.animationNames.add(animation.name);
                        }
                    }
                }
            }
            if (skelToReturn != null)
                return skelToReturn;
            else
                return null;
        } catch (Exception e)
        {
            e.printStackTrace();
        }

        return null;
    }



这里是我用来测试解析器的代码片段:

AnimationSystem animator = new AnimationSystem();
        try {
            skeleton = animator.parseSkeletonFile(getClass().getResource("SkeletonTest.xml").getPath());
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        if (skeleton != null)
        {
            System.out.println(skeleton.name);
        }


这是在Slick2D中构建的简单游戏的init方法。我正在尝试加载的文件SkeletonTest.xml与调用解析方法的类位于同一个包中。它的内容很简单:

<skeleton name="TestSkeleton">

</skeleton>



这是我收到的错误信息:

java.io.FileNotFoundException: D:\Eclipse%20Workspace\2dSkeletalAnimator\bin\org\jason\animatorTests\SkeletonTest.xml (The system cannot find the path specified)
    at java.io.FileInputStream.open(Native Method)
    at java.io.FileInputStream.<init>(Unknown Source)
    at java.io.FileInputStream.<init>(Unknown Source)
    at sun.net.www.protocol.file.FileURLConnection.connect(Unknown Source)
    at sun.net.www.protocol.file.FileURLConnection.getInputStream(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(Unknown Source)
    at javax.xml.parsers.DocumentBuilder.parse(Unknown Source)
    at org.jason.skeletalanimator.AnimationSystem.parseSkeletonFile(AnimationSystem.java:42)
    at org.jason.animatorTests.AnimatorTest1.init(AnimatorTest1.java:32)
    at org.newdawn.slick.AppGameContainer.setup(AppGameContainer.java:433)
    at org.newdawn.slick.AppGameContainer.start(AppGameContainer.java:357)
    at org.jason.animatorTests.AnimatorTest1.main(AnimatorTest1.java:65)



对于一些一般性的问题和所需的背景信息量感到抱歉,但我已经尝试了一切,以便在重写解析方法的主体之前解决这个问题。我宁愿不再经历那一团糟。所以我希望有更多从XML样式文件加载数据经验的人可以帮助我。我感谢任何提前给我一些时间的人。

2 个答案:

答案 0 :(得分:3)

一个问题是您尝试从类路径条目中获取FilegetPath()方法返回文件URL,而不是文件路径。然后,您尝试加载它,就像它是文件路径一样,这会导致问题。

如果你使用getClass().getResourceAsStream()给你一个InputStream,那将会容易得多。

您可以将location传递给InputStream方法,然后更改为使用DocumentBuilder#parse(InputStream),而不是传递parseSkeleton

使用InputStream的另一个好处是,如果您将类打包在JAR文件中,您仍然可以加载资源(您将无法获得有效的File路径进入你的JAR)。或者您的骨架定义可能来自任何其他InputStream,例如网络等。

答案 1 :(得分:0)

java.io.FileNotFoundException:D:\ Eclipse%20Workspace \ 2dSkeletalAnimator \ bin \ org \ jason \ animatorTests \ SkeletonTest.xml(系统找不到指定的路径)

你的道路上有一个空间。这就是问题。请注意%20。我无法看到它被编码的位置,但您应该在拨打电话之前解码文件路径。